Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e5af62e
feat: plan agent refinement, feature discovery, and telemetry instrum…
anandgupta42 Mar 29, 2026
57a2e78
fix: address CodeRabbit review comments
anandgupta42 Mar 29, 2026
7384fe2
feat: e2e tests, performance benchmarks, and UX gap fixes
anandgupta42 Mar 29, 2026
1fc5c05
test: plan layer safety e2e tests (68 tests)
anandgupta42 Mar 29, 2026
a5b4e44
merge: resolve conflicts with main (skill followups + sql findings)
anandgupta42 Mar 29, 2026
bc4287b
fix: add mongodb to devDependencies for typecheck resolution
anandgupta42 Mar 29, 2026
77dae71
Merge branch 'main' into feat/plan-agent-and-feature-discovery
anandgupta42 Mar 29, 2026
b24d84e
Merge branch 'main' into feat/plan-agent-and-feature-discovery
anandgupta42 Mar 29, 2026
17f4a19
fix: track suggestion failures in warehouse-add telemetry
anandgupta42 Mar 29, 2026
3b78d42
test: 125 simulated user scenarios for plan + suggestions
anandgupta42 Mar 29, 2026
adb6c7e
test: 40 real tool execution simulations with mocked Dispatcher
anandgupta42 Mar 29, 2026
3f5fcb3
docs: document plan refinement, feature discovery, and new telemetry …
anandgupta42 Mar 29, 2026
24234ff
fix: replace mock.module() with spyOn to prevent cross-file test poll…
anandgupta42 Mar 29, 2026
734d173
fix: reset dedup state in tests + replace passwords with fake values
anandgupta42 Mar 29, 2026
63b1dbd
Merge branch 'main' into feat/plan-agent-and-feature-discovery
anandgupta42 Mar 29, 2026
11bb99d
fix: replace all credential-like test values for GitGuardian
anandgupta42 Mar 29, 2026
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
32 changes: 32 additions & 0 deletions packages/opencode/src/altimate/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ export namespace Telemetry {
skill_name: string
skill_source: "builtin" | "global" | "project"
duration_ms: number
// altimate_change start — skill trigger classification for discovery analytics
trigger: "user_command" | "llm_selected" | "auto_suggested" | "unknown"
// altimate_change end
}
// altimate_change start — first_launch event for new user counting (privacy-safe: only version + machine_id)
| {
Expand Down Expand Up @@ -385,6 +388,15 @@ export namespace Telemetry {
source: "cli" | "tui"
}
// altimate_change end
// altimate_change start — plan refinement telemetry event
| {
type: "plan_revision"
timestamp: number
session_id: string
revision_number: number
action: "refine" | "approve" | "reject"
}
// altimate_change end
| {
type: "sql_execute_failure"
timestamp: number
Expand All @@ -395,6 +407,16 @@ export namespace Telemetry {
masked_sql: string
duration_ms: number
}
// altimate_change start — feature_suggestion event for post-connect and progressive disclosure tracking
| {
type: "feature_suggestion"
timestamp: number
session_id: string
suggestion_type: "post_warehouse_connect" | "dbt_detected" | "schema_not_indexed" | "progressive_disclosure"
suggestions_shown: string[]
warehouse_type?: string
}
// altimate_change end
| {
type: "core_failure"
timestamp: number
Expand Down Expand Up @@ -561,6 +583,16 @@ export namespace Telemetry {
return "standard"
}

// altimate_change start — classify how a skill was triggered for discovery analytics
export function classifySkillTrigger(extra?: { [key: string]: any }): "user_command" | "llm_selected" | "auto_suggested" | "unknown" {
if (!extra) return "llm_selected"
if (extra.trigger === "user_command") return "user_command"
if (extra.trigger === "auto_suggested") return "auto_suggested"
if (extra.trigger === "llm_selected") return "llm_selected"
return "llm_selected"
}
// altimate_change end

export function bucketCount(n: number): string {
if (n <= 0) return "0"
if (n <= 10) return "1-10"
Expand Down
106 changes: 106 additions & 0 deletions packages/opencode/src/altimate/tools/post-connect-suggestions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Post-connect feature suggestions and progressive disclosure.
*
* After warehouse connect, users often don't know what to do next.
* This module provides contextual suggestions based on the user's
* environment and progressive next-step hints after tool usage.
*/

import { Telemetry } from "../../telemetry"

export namespace PostConnectSuggestions {
export interface SuggestionContext {
warehouseType: string
schemaIndexed: boolean
dbtDetected: boolean
connectionCount: number
toolsUsedInSession: string[]
}

export function getPostConnectSuggestions(ctx: SuggestionContext): string {
const suggestions: string[] = []

if (!ctx.schemaIndexed) {
suggestions.push(
"Index your schema — enables SQL analysis, column-level lineage, and data quality checks. Use the schema_index tool.",
)
}

suggestions.push(
"Run SQL queries against your " +
ctx.warehouseType +
" warehouse using sql_execute",
)
suggestions.push(
"Analyze SQL quality and find potential issues with sql_analyze",
)

if (ctx.dbtDetected) {
suggestions.push(
"dbt project detected — try /dbt-develop to help build models or /dbt-troubleshoot to debug issues",
)
}

suggestions.push(
"Trace data lineage across your models with lineage_check",
)
suggestions.push("Audit for PII exposure with schema_detect_pii")

if (ctx.connectionCount > 1) {
suggestions.push("Compare data across warehouses with data_diff")
}

return (
"\n\n---\nAvailable capabilities for your " +
ctx.warehouseType +
" warehouse:\n" +
suggestions.map((s, i) => `${i + 1}. ${s}`).join("\n")
)
}

/**
* Progressive disclosure: suggest next tool based on what was just used.
* Returns null if no suggestion applies or tool is unknown.
*/
export function getProgressiveSuggestion(
lastToolUsed: string,
): string | null {
const progression: Record<string, string | null> = {
sql_execute:
"Tip: Use sql_analyze to check this query for potential issues, performance optimizations, and best practices.",
sql_analyze:
"Tip: Use schema_inspect to explore the tables and columns referenced in your query.",
schema_inspect:
"Tip: Use lineage_check to see how this data flows through your models.",
schema_index:
"Schema indexed! You can now use sql_analyze for quality checks, schema_inspect for exploration, and lineage_check for data flow analysis.",
warehouse_add: null, // Handled by post-connect suggestions
}
return progression[lastToolUsed] ?? null
}

/**
* Track that feature suggestions were shown, for measuring discovery rates.
*/
export function trackSuggestions(opts: {
suggestionType:
| "post_warehouse_connect"
| "dbt_detected"
| "progressive_disclosure"
suggestionsShown: string[]
warehouseType?: string
}): void {
try {
Telemetry.track({
type: "feature_suggestion",
timestamp: Date.now(),
session_id: Telemetry.getContext().sessionId,
suggestion_type: opts.suggestionType,
suggestions_shown: opts.suggestionsShown,
warehouse_type: opts.warehouseType ?? "unknown",
})
} catch {
// Telemetry must never break tool execution
}
}
}
17 changes: 17 additions & 0 deletions packages/opencode/src/altimate/tools/project-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,23 @@ export const ProjectScanTool = Tool.define("project_scan", {
if (dbtProject.hasPackages) {
lines.push(` ✓ packages.yml or dependencies.yml found`)
}
// altimate_change start — dbt auto-detection skill suggestions
lines.push("")
lines.push(` Recommended skills:`)
lines.push(` - /dbt-develop — Build and modify dbt models with AI assistance`)
lines.push(` - /dbt-troubleshoot — Debug failing dbt models and tests`)
lines.push(` - /dbt-analyze — Analyze dbt project structure and dependencies`)

try {
const { PostConnectSuggestions } = await import("./post-connect-suggestions")
PostConnectSuggestions.trackSuggestions({
suggestionType: "dbt_detected",
suggestionsShown: ["dbt_develop", "dbt_troubleshoot", "dbt_analyze"],
})
} catch {
// Telemetry must never break scan output
}
// altimate_change end
} else {
lines.push("✗ No dbt_project.yml found")
}
Expand Down
17 changes: 16 additions & 1 deletion packages/opencode/src/altimate/tools/schema-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import z from "zod"
import { Tool } from "../../tool/tool"
import { Dispatcher } from "../native"
import type { SchemaIndexResult } from "../native/types"
// altimate_change start — progressive disclosure suggestions
import { PostConnectSuggestions } from "./post-connect-suggestions"
// altimate_change end

export const SchemaIndexTool = Tool.define("schema_index", {
description:
Expand All @@ -15,14 +18,26 @@ export const SchemaIndexTool = Tool.define("schema_index", {
warehouse: args.warehouse,
})

// altimate_change start — progressive disclosure suggestions
let output = formatIndexResult(result)
const suggestion = PostConnectSuggestions.getProgressiveSuggestion("schema_index")
if (suggestion) {
output += "\n\n" + suggestion
PostConnectSuggestions.trackSuggestions({
suggestionType: "progressive_disclosure",
suggestionsShown: ["sql_analyze", "schema_inspect", "lineage_check"],
warehouseType: result.type,
})
}
// altimate_change end
return {
title: `Schema Indexed: ${result.warehouse}`,
metadata: {
schemas: result.schemas_indexed,
tables: result.tables_indexed,
columns: result.columns_indexed,
},
output: formatIndexResult(result),
output,
}
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
Expand Down
16 changes: 15 additions & 1 deletion packages/opencode/src/altimate/tools/schema-inspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import z from "zod"
import { Tool } from "../../tool/tool"
import { Dispatcher } from "../native"
import type { SchemaInspectResult } from "../native/types"
// altimate_change start — progressive disclosure suggestions
import { PostConnectSuggestions } from "./post-connect-suggestions"
// altimate_change end

export const SchemaInspectTool = Tool.define("schema_inspect", {
description: "Inspect database schema — list columns, types, and constraints for a table.",
Expand All @@ -18,10 +21,21 @@ export const SchemaInspectTool = Tool.define("schema_inspect", {
warehouse: args.warehouse,
})

// altimate_change start — progressive disclosure suggestions
let output = formatSchema(result)
const suggestion = PostConnectSuggestions.getProgressiveSuggestion("schema_inspect")
if (suggestion) {
output += "\n\n" + suggestion
PostConnectSuggestions.trackSuggestions({
suggestionType: "progressive_disclosure",
suggestionsShown: ["lineage_check"],
})
}
// altimate_change end
return {
title: `Schema: ${result.table}`,
metadata: { columnCount: result.columns.length, rowCount: result.row_count },
output: formatSchema(result),
output,
}
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
Expand Down
16 changes: 15 additions & 1 deletion packages/opencode/src/altimate/tools/sql-analyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import z from "zod"
import { Tool } from "../../tool/tool"
import { Dispatcher } from "../native"
import type { SqlAnalyzeResult } from "../native/types"
// altimate_change start — progressive disclosure suggestions
import { PostConnectSuggestions } from "./post-connect-suggestions"
// altimate_change end

export const SqlAnalyzeTool = Tool.define("sql_analyze", {
description:
Expand All @@ -21,6 +24,17 @@ export const SqlAnalyzeTool = Tool.define("sql_analyze", {
dialect: args.dialect,
})

// altimate_change start — progressive disclosure suggestions
let output = formatAnalysis(result)
const suggestion = PostConnectSuggestions.getProgressiveSuggestion("sql_analyze")
if (suggestion) {
output += "\n\n" + suggestion
PostConnectSuggestions.trackSuggestions({
suggestionType: "progressive_disclosure",
suggestionsShown: ["schema_inspect"],
})
}
// altimate_change end
return {
title: `Analyze: ${result.error ? "PARSE ERROR" : `${result.issue_count} issue${result.issue_count !== 1 ? "s" : ""}`} [${result.confidence}]`,
metadata: {
Expand All @@ -29,7 +43,7 @@ export const SqlAnalyzeTool = Tool.define("sql_analyze", {
confidence: result.confidence,
...(result.error && { error: result.error }),
},
output: formatAnalysis(result),
output,
}
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
Expand Down
16 changes: 15 additions & 1 deletion packages/opencode/src/altimate/tools/sql-execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import type { SqlExecuteResult } from "../native/types"
// altimate_change start - SQL write access control
import { classifyAndCheck } from "./sql-classify"
// altimate_change end
// altimate_change start — progressive disclosure suggestions
import { PostConnectSuggestions } from "./post-connect-suggestions"
// altimate_change end

export const SqlExecuteTool = Tool.define("sql_execute", {
description: "Execute SQL against a connected data warehouse. Returns results as a formatted table.",
Expand Down Expand Up @@ -37,7 +40,18 @@ export const SqlExecuteTool = Tool.define("sql_execute", {
limit: args.limit,
})

const output = formatResult(result)
let output = formatResult(result)
// altimate_change start — progressive disclosure suggestions
const suggestion = PostConnectSuggestions.getProgressiveSuggestion("sql_execute")
if (suggestion) {
output += "\n\n" + suggestion
PostConnectSuggestions.trackSuggestions({
suggestionType: "progressive_disclosure",
suggestionsShown: ["sql_analyze"],
warehouseType: args.warehouse ?? "default",
})
}
// altimate_change end
return {
title: `SQL: ${args.query.slice(0, 60)}${args.query.length > 60 ? "..." : ""}`,
metadata: { rowCount: result.row_count, truncated: result.truncated },
Expand Down
44 changes: 43 additions & 1 deletion packages/opencode/src/altimate/tools/warehouse-add.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import z from "zod"
import { Tool } from "../../tool/tool"
import { Dispatcher } from "../native"
// altimate_change start — post-connect feature suggestions
import { PostConnectSuggestions } from "./post-connect-suggestions"
// altimate_change end

export const WarehouseAddTool = Tool.define("warehouse_add", {
description:
Expand Down Expand Up @@ -41,10 +44,49 @@ IMPORTANT: For private key file paths, always use "private_key_path" (not "priva
})

if (result.success) {
// altimate_change start — append post-connect feature suggestions
let output = `Successfully added warehouse '${result.name}' (type: ${result.type}).\n\nUse warehouse_test to verify connectivity.`
try {
const schemaCache = await Dispatcher.call("schema.cache_status", {}).catch(() => null)
const schemaIndexed = (schemaCache?.total_tables ?? 0) > 0
const warehouseList = await Dispatcher.call("warehouse.list", {}).catch(() => ({ warehouses: [] }))

let dbtDetected = false
try {
const { detectDbtProject } = await import("./project-scan")
const dbtInfo = await detectDbtProject(process.cwd())
dbtDetected = dbtInfo.found
} catch {
// project-scan unavailable — skip dbt detection
}

const ctx: PostConnectSuggestions.SuggestionContext = {
warehouseType: result.type,
schemaIndexed,
dbtDetected,
connectionCount: warehouseList.warehouses.length,
toolsUsedInSession: [],
}
output += PostConnectSuggestions.getPostConnectSuggestions(ctx)

const suggestionsShown = ["sql_execute", "sql_analyze", "lineage_check", "schema_detect_pii"]
if (!schemaIndexed) suggestionsShown.unshift("schema_index")
if (dbtDetected) suggestionsShown.push("dbt_develop", "dbt_troubleshoot")
if (warehouseList.warehouses.length > 1) suggestionsShown.push("data_diff")
PostConnectSuggestions.trackSuggestions({
suggestionType: "post_warehouse_connect",
suggestionsShown,
warehouseType: result.type,
})
} catch {
// Suggestions must never break the add flow
Copy link
Copy Markdown
Contributor

@suryaiyer95 suryaiyer95 Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion
Can add telemetry on these failures?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — added core_failure telemetry with error_class: "suggestion_failure" in the catch block. This way we can track how often suggestions fail and what errors occur, without breaking the warehouse add flow.

Pushed in the latest commit.

}
// altimate_change end

return {
title: `Add '${args.name}': OK`,
metadata: { success: true, name: result.name, type: result.type },
output: `Successfully added warehouse '${result.name}' (type: ${result.type}).\n\nUse warehouse_test to verify connectivity.`,
output,
}
}

Expand Down
Loading
Loading