Skip to content

feat: add core_failure telemetry with PII-safe input signatures#245

Merged
suryaiyer95 merged 14 commits intomainfrom
feat/core-failure-telemetry
Mar 19, 2026
Merged

feat: add core_failure telemetry with PII-safe input signatures#245
suryaiyer95 merged 14 commits intomainfrom
feat/core-failure-telemetry

Conversation

@suryaiyer95
Copy link
Contributor

@suryaiyer95 suryaiyer95 commented Mar 18, 2026

Summary

  • Add core_failure telemetry event with PII-masked arguments aligned to Rust SDK (altimate-sdk)
  • Emit core_failure on both soft failures (metadata.success === false) and uncaught exceptions — captures 99% of real tool failures
  • Add maskArgs() mirroring Rust SDK masking: 19 sensitive keys with prefix/suffix matching, SQL string literals replaced with ?, whitespace collapsed
  • Add classifyError(): keyword-based error classification into 7 categories
  • Add computeInputSignature(): records key names + value types/lengths only
  • Add input_signature to tool_call events on failures
  • Fix 60x telemetry flush duplication bug: drop events on network error instead of re-queuing

Companion PR: https://github.com/AltimateAI/altimate-core-internal/pull/109

Privacy

  • masked_args: SQL string literals → ?, sensitive keys → "****", structure preserved
  • input_signature: key names + value types/lengths only — no actual values
  • error_message: truncated to 500 chars
  • No raw SQL, credentials, file paths, or PII in any field

Verified in Azure App Insights

  • tool_call events with input_signature on failures confirmed
  • core_failure events with masked_args ready (needs interactive session)
  • Flush duplication fixed: 0 duplicates after fix (was 60x before)

Test plan

  • 89 telemetry tests pass
  • classifyError() — 7 categories + case insensitivity (8 tests)
  • computeInputSignature() — all value types + truncation (8 tests)
  • maskArgs() — SQL literals, sensitive keys, structure preservation, escaped quotes, truncation (7 tests)
  • core_failure privacy validation (3 tests)
  • Flush retry test updated for drop-on-error behavior

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added skill_used and sql_execute_failure telemetry events; richer tool_call telemetry (timing, input signature, masked args).
    • Introduced anonymous machine ID for diagnostics.
  • Bug Fixes / Privacy

    • Improved privacy: masked/truncated SQL, error messages, and sensitive arguments in telemetry.
    • SQL execute now returns the full error string to callers (telemetry still masks/truncates as documented).
  • Documentation

    • Updated telemetry docs and event name (bridge_call → native_call).
  • Tests

    • Expanded telemetry tests for new events, masking, classification, and truncation.

Copilot AI review requested due to automatic review settings March 18, 2026 05:49
@claude
Copy link

claude bot commented Mar 18, 2026

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR expands Opencode’s telemetry by adding a new core_failure event (with privacy-preserving input signatures and coarse error classification) and emits additional telemetry from the tool execution wrapper, while updating tests and docs to reflect the updated event surface.

Changes:

  • Add core_failure to Telemetry.Event, plus classifyError() and computeInputSignature() helpers.
  • Emit tool_call telemetry (success/error) from Tool.define() and emit core_failure telemetry on thrown errors.
  • Update telemetry tests for the expanded event type set and add unit tests for the new helpers and privacy guarantees.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
packages/opencode/test/telemetry/telemetry.test.ts Updates event type lists and adds tests for classifyError, computeInputSignature, and core_failure privacy constraints.
packages/opencode/src/tool/tool.ts Emits tool_call telemetry for tool execution and emits core_failure on exceptions, including truncated error text and input signatures.
packages/opencode/src/altimate/telemetry/index.ts Adds the core_failure event type and implements error classification + input signature computation.
docs/docs/configure/telemetry.md Updates telemetry documentation and adds a new “Core Engine Telemetry” section (currently inconsistent with the implemented events/fields).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch 3 times, most recently from 1e86cf0 to a16fb16 Compare March 18, 2026 09:11
@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch 2 times, most recently from 8099906 to 687494e Compare March 18, 2026 17:14
Comment on lines +358 to +368
}> = [
{ class: "parse_error", keywords: ["parse", "syntax", "binder", "unexpected token", "sqlglot"] },
{
class: "connection",
keywords: ["econnrefused", "connection", "socket", "enotfound", "econnreset"],
},
{ class: "timeout", keywords: ["timeout", "etimedout", "bridge timeout", "timed out"] },
{ class: "validation", keywords: ["invalid params", "invalid", "missing", "required"] },
{ class: "permission", keywords: ["permission", "denied", "unauthorized", "forbidden"] },
{ class: "internal", keywords: ["internal", "assertion"] },
]

This comment was marked as outdated.

Add a new `core_failure` event emitted on both soft failures
(`metadata.success === false`) and uncaught tool exceptions, with
privacy-preserving context for debugging:

- `classifyError()` — keyword-based error classification (parse, connection, timeout, validation, permission, internal, unknown)
- `computeInputSignature()` — records key names + value types/lengths, never actual values; truncates by dropping keys to preserve valid JSON
- `maskArgs()` — PII masking aligned to Rust SDK: 19 sensitive keys redacted, string literals in SQL replaced with `?`, recursive object traversal

Telemetry is fully isolated from tool execution — all tracking calls
are wrapped in `try/catch` so telemetry failures never break tools.
`Truncate.output()` runs outside the telemetry error boundary so I/O
errors aren't misattributed as tool failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch from 687494e to 38fb986 Compare March 18, 2026 23:39
Tracks which skill is loaded and where it came from (`builtin`, `global`,
or `project`) with duration. Wrapped in try/catch — cannot break skill
loading. Docs table updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch from 38fb986 to 2e73f2e Compare March 18, 2026 23:44
\`core_failure\` is for internal tool failures. SQL execution via the
dispatcher is a separate concern — soft errors are returned as results
(not thrown), so \`core_failure\` never fires for them.

New \`sql_execute_failure\` event captures: warehouse type, query type,
error message (truncated to 500 chars), and PII-masked SQL. Fires from
the \`sql.execute\` handler catch path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch from 4e47382 to ef1d1a7 Compare March 19, 2026 00:24
Generated once as a random UUID and stored at \`~/.altimate/machine-id\`
(alongside \`altimate.json\`, \`connections.json\`, etc.). Sent as
\`machine_id\` in \`customDimensions\` on every App Insights event.
No PII — pure random UUID, never tied to user identity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@suryaiyer95 suryaiyer95 force-pushed the feat/core-failure-telemetry branch from fbc2375 to 625f3f4 Compare March 19, 2026 00:50
warehouse_type: warehouseType,
query_type: detectQueryType(params.sql),
error_message: errorMsg.slice(0, 500),
masked_sql: Telemetry.maskArgs({ sql: params.sql }),

This comment was marked as outdated.

@suryaiyer95
Copy link
Contributor Author

Code review

Found 4 issues:

  1. masked_sql sends a JSON object string instead of the raw masked SQL — Telemetry.maskArgs({ sql: params.sql }) returns '{"sql":"SELECT ..."} (a JSON-serialized object), not the masked SQL string. Should be Telemetry.maskString(params.sql) instead.

query_type: detectQueryType(params.sql),
error_message: errorMsg.slice(0, 500),
masked_sql: Telemetry.maskArgs({ sql: params.sql }),
duration_ms: Date.now() - startTime,
})
} catch {}

  1. ERROR_PATTERNS ordering — the validation pattern uses the broad keyword "invalid" and appears before the permission pattern. An error like "Invalid permission denied" will be classified as validation_error instead of permission_denied. The permission pattern should appear before validation.

{ class: "parse_error", keywords: ["parse", "syntax", "binder", "unexpected token", "sqlglot"] },
{
class: "connection",
keywords: ["econnrefused", "connection", "socket", "enotfound", "econnreset"],
},
{ class: "timeout", keywords: ["timeout", "etimedout", "bridge timeout", "timed out"] },
{ class: "validation", keywords: ["invalid params", "invalid", "missing", "required"] },
{ class: "permission", keywords: ["permission", "denied", "unauthorized", "forbidden"] },
{ class: "internal", keywords: ["internal", "assertion"] },
]
export function classifyError(
message: string,
): Telemetry.Event & { type: "core_failure" } extends { error_class: infer C } ? C : never {
const lower = message.toLowerCase()
for (const { class: cls, keywords } of ERROR_PATTERNS) {
if (keywords.some((kw) => lower.includes(kw))) return cls
}
return "unknown"
}

  1. core_failure error_message for soft failures falls back to result.output?.slice(0, 500) when result.metadata.error is not a string. Tool output can contain raw query results or other sensitive data — this may leak unmasked content into telemetry.

tool_type: "standard",
tool_category: Telemetry.categorizeToolName(id, "standard"),
status: "error",
duration_ms: Date.now() - startTime,
sequence_index: 0,
previous_tool: null,
input_signature: Telemetry.computeInputSignature(args as Record<string, unknown>),
error: errorMsg.slice(0, 500),
})
Telemetry.track({
type: "core_failure",
timestamp: Date.now(),
session_id: ctx.sessionID,
tool_name: id,
tool_category: Telemetry.categorizeToolName(id, "standard"),
error_class: Telemetry.classifyError(errorMsg),

  1. isSensitiveKey() over-masks the auth_method field — the prefix check k.startsWith("auth_") matches auth_method, which holds non-sensitive enum values like "keypair" or "password". This redacts useful debugging signal. auth_method should be explicitly excluded.

auth_method: string
success: boolean
duration_ms: number
error?: string
error_category?: string
}
| {
type: "warehouse_query"
timestamp: number
session_id: string
warehouse_type: string
query_type: string
success: boolean
duration_ms: number
row_count: number
truncated: boolean

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

suryaiyer95 and others added 5 commits March 18, 2026 18:11
…metry

- `sql_execute_failure`: use `Telemetry.maskString(params.sql)` instead of
  `Telemetry.maskArgs({ sql: params.sql })` — the latter serializes a JSON
  object string `{"sql":"..."}` rather than the raw masked SQL
- `ERROR_PATTERNS`: move `permission` before `validation` so errors like
  "Invalid permission denied" are not misclassified as `validation_error`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Read/write/edit/glob/grep/bash succeed constantly in normal operation —
tracking every success is high-volume noise with no actionable signal.
Failures (hard throws and soft failures) are still fully captured via
\`tool_call\` (status=error) and \`core_failure\`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Error messages from SQL engines can embed data values (e.g.
"Value 'john@email.com' does not match type INTEGER"). Apply
maskString() to all error_message fields before transmission,
consistent with how args are already masked.

Affects: core_failure (tool.ts), sql_execute_failure (register.ts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds telemetry event types and privacy utilities, instruments tool/skill execution and SQL error paths with masked reporting, persists a machine ID to ~/.altimate/machine-id, updates tests/docs, and removes a single TypeScript comment in the SQL Server driver.

Changes

Cohort / File(s) Summary
Telemetry Core
packages/opencode/src/altimate/telemetry/index.ts
Expanded Telemetry.Event (added input_signature, skill_used, sql_execute_failure, core_failure), added classifyError, computeInputSignature, maskString, maskArgs, persistent machineId read/write, and adjusted AppInsights envelope generation.
Tool Execution
packages/opencode/src/tool/tool.ts
Instrumented tool execution with timing and telemetry; emits tool_call and core_failure events, computes input signatures and masked args, and ensures telemetry failures are swallowed while preserving original errors/results.
Skill Execution
packages/opencode/src/tool/skill.ts
Records skill_used telemetry with duration and classifies skill source (builtin/global/project); telemetry errors are caught and ignored.
SQL / Connection Paths
packages/opencode/src/altimate/native/connections/register.ts, packages/opencode/src/altimate/native/connections/registry.ts, packages/opencode/src/altimate/native/dispatcher.ts
Sanitizes error text via Telemetry.maskString before truncation; register.ts emits new sql_execute_failure events including masked_sql, masked error, query type and duration.
Tests & Docs
packages/opencode/test/telemetry/telemetry.test.ts, docs/docs/reference/telemetry.md
Expanded tests for classification/masking/signature APIs and privacy assertions; docs updated (renamed bridge_callnative_call, added new events, documented machine-id behavior).
Minor Cleanup
packages/drivers/src/sqlserver.ts
Removed a single // @ts-expect-error`` comment from a dynamic mssql import.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Runner as Tool/Skill Runner
  participant Telemetry as Telemetry
  participant FS as Filesystem (~/.altimate)
  participant DB as Database / SQL Driver
  participant App as AppInsights

  Runner->>Telemetry: init -> read/write machine-id (UUID)
  Runner->>Telemetry: start telemetry (timestamp, session_id)
  Runner->>DB: execute query or invoke tool/skill
  DB-->>Runner: result or error
  alt success
    Runner->>Telemetry: compute input_signature, maskArgs -> track tool_call (success)
    Telemetry->>App: send envelope (includes machine_id)
  else error or soft-failure
    Runner->>Telemetry: classifyError, maskString(masked_sql) -> track core_failure / sql_execute_failure / tool_call(error)
    Telemetry->>App: send envelope (masked fields)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hop to hide each quoting trace,

UUID snug in a secret place,
skills and queries timed with care,
masked strings dancing in the air,
privacy kept in every grace.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically describes the main feature being added: a new core_failure telemetry event with PII-safe input signatures.
Description check ✅ Passed The PR description comprehensively covers the summary of changes, test plan with specifics (89 tests passing, specific test categories), and includes documentation updates. All required template sections are present and well-populated.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/core-failure-telemetry
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/opencode/src/altimate/telemetry/index.ts (1)

444-449: isSensitiveKey() over-masks auth_method (and similar enum-valued fields).

The prefix check lower.startsWith(${k}_) matches keys like auth_method against the auth sensitive key. However, auth_method typically holds non-sensitive enum values (e.g., "keypair", "password", "oauth") that are useful for debugging warehouse connection issues.

Consider explicitly excluding known safe keys:

🛠️ Suggested fix
+const SAFE_KEYS = new Set(["auth_method", "auth_type"])
+
 function isSensitiveKey(key: string): boolean {
   const lower = key.toLowerCase()
+  if (SAFE_KEYS.has(lower)) return false
   return SENSITIVE_KEYS.some(
     (k) => lower === k || lower.endsWith(`_${k}`) || lower.startsWith(`${k}_`),
   )
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/altimate/telemetry/index.ts` around lines 444 - 449,
The isSensitiveKey function currently over-masks keys like auth_method because
lower.startsWith(`${k}_`) matches "auth_" prefixes; update isSensitiveKey to
explicitly whitelist known safe enum-like fields (e.g., "auth_method", maybe
"auth_type", or other domain-specific non-sensitive keys) before applying the
generic SENSITIVE_KEYS checks so those keys are not treated as sensitive. Locate
and modify the isSensitiveKey function and the SENSITIVE_KEYS usage to first
check a SAFE_KEYS set (or explicit exclusions) and return false for those names,
then fall back to the existing equality/endsWith/startsWith logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/tool/tool.ts`:
- Around line 137-155: The soft-failure telemetry currently falls back to
result.output which may contain unmasked PII; update the error selection in the
isSoftFailure block (where result.metadata?.error, result.output,
Telemetry.maskString and Telemetry.track are used) so it does NOT directly use
result.output — either (A) only use result.metadata.error when it's a string and
otherwise use a safe constant like "unknown error", or (B) if you must include
output context, pass result.output through a stronger sanitizer before masking
(implement or call a Telemetry.sanitizePII/Telemetry.redactPII helper that
strips emails/IPs/IDs, then call Telemetry.maskString on the sanitized text) and
use that sanitized-and-masked value as error_message in Telemetry.track.

---

Nitpick comments:
In `@packages/opencode/src/altimate/telemetry/index.ts`:
- Around line 444-449: The isSensitiveKey function currently over-masks keys
like auth_method because lower.startsWith(`${k}_`) matches "auth_" prefixes;
update isSensitiveKey to explicitly whitelist known safe enum-like fields (e.g.,
"auth_method", maybe "auth_type", or other domain-specific non-sensitive keys)
before applying the generic SENSITIVE_KEYS checks so those keys are not treated
as sensitive. Locate and modify the isSensitiveKey function and the
SENSITIVE_KEYS usage to first check a SAFE_KEYS set (or explicit exclusions) and
return false for those names, then fall back to the existing
equality/endsWith/startsWith logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ed820b8c-eb56-4650-acd6-3cb8af05b32e

📥 Commits

Reviewing files that changed from the base of the PR and between f27dc39 and 2625f42.

📒 Files selected for processing (7)
  • docs/docs/configure/telemetry.md
  • packages/drivers/src/sqlserver.ts
  • packages/opencode/src/altimate/native/connections/register.ts
  • packages/opencode/src/altimate/telemetry/index.ts
  • packages/opencode/src/tool/skill.ts
  • packages/opencode/src/tool/tool.ts
  • packages/opencode/test/telemetry/telemetry.test.ts
💤 Files with no reviewable changes (1)
  • packages/drivers/src/sqlserver.ts

- Mask error messages in `native_call` (dispatcher.ts) and `warehouse_connect` (registry.ts) — these were sending raw error strings that could embed credentials or query fragments
- Fix soft-failure `error_message` fallback: drop `result.output` as a source (raw tool output could contain file contents or secrets); fall back to `"unknown error"` instead
- Strip `_retried` internal flag from App Insights payload — was leaking into `properties` on retried events
- Add camelCase variants to `SENSITIVE_KEYS` (`authToken`, `bearerToken`, `jwtSecret`, etc.) — underscore prefix/suffix matching missed these
- Document `machine_id` in telemetry privacy docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/altimate/telemetry/index.ts`:
- Around line 447-452: The isSensitiveKey function is over-masking keys like
"auth_method" because the startsWith(`${k}_`) rule matches "auth_..." entries;
update isSensitiveKey (and its use of SENSITIVE_KEYS and the lower variable) to
explicitly exclude "auth_method" (or check for exact "auth_method" and return
false) before applying the generic startsWith/endsWith/equality rules so that
non-sensitive enum values (e.g., "keypair", "password", "sso") are not redacted
in telemetry.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5588fd2e-fa95-4ce9-9ddf-460f65b22665

📥 Commits

Reviewing files that changed from the base of the PR and between 2625f42 and c95f7b3.

📒 Files selected for processing (5)
  • docs/docs/configure/telemetry.md
  • packages/opencode/src/altimate/native/connections/registry.ts
  • packages/opencode/src/altimate/native/dispatcher.ts
  • packages/opencode/src/altimate/telemetry/index.ts
  • packages/opencode/src/tool/tool.ts

…ence/telemetry.md

Main renamed the file; keep `native_call` (replaces deprecated `bridge_call`) and
correct contributor file path (`packages/opencode/src/altimate/telemetry/index.ts`).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/docs/reference/telemetry.md (1)

81-81: ⚠️ Potential issue | 🟡 Minor

Fix contradiction: masked SQL is collected, but raw SQL is not.

Line 81 states that "SQL queries" are never collected, but line 37 documents that sql_execute_failure events include "PII-masked SQL." This is contradictory.

According to the PR objectives, the privacy claim is "no raw SQL" (not "no SQL at all"). Masked SQL with literals replaced by ? is intentionally collected for diagnostics.

Update line 81 to clarify:

-- SQL queries or query results
+- Raw SQL queries or query results (masked SQL with literals replaced by `?` may be included in error events)

This maintains transparency about what is and isn't collected.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/reference/telemetry.md` at line 81, Update the sentence that
currently reads "SQL queries or query results" to clarify that raw SQL is not
collected but PII-masked SQL (with literals replaced by ?), such as the SQL
included in sql_execute_failure events, is collected for diagnostics; explicitly
state "raw/unmasked SQL is never collected; PII-masked SQL (literals replaced by
'?') may be collected (e.g. in sql_execute_failure events)" so the doc aligns
with the recorded event behavior.
🧹 Nitpick comments (1)
docs/docs/reference/telemetry.md (1)

15-15: Consider documenting input_signature on tool_call failures.

According to the PR objectives, tool_call events now include an input_signature field when failures occur. This is a key privacy-enhancing feature that records only key names, value types, and lengths—not raw values. Consider updating the description to mention this field is added on failures, e.g.:

| `tool_call` | A tool is invoked (tool name and category — no arguments or output; on failures, includes a PII-safe `input_signature`) |

This helps users understand the privacy guarantees around failure diagnostics.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/reference/telemetry.md` at line 15, Update the `tool_call` table
entry to mention the new `input_signature` field added on failures: change the
description for `tool_call` to note that when a tool invocation fails it
includes a PII-safe `input_signature` (records only key names, value types, and
lengths — not raw values) so readers know failures include this
privacy-preserving diagnostic info; reference `tool_call` and `input_signature`
in the updated sentence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/docs/reference/telemetry.md`:
- Line 38: Update the `core_failure` event description to match the actual event
fields: replace "function name" with "tool name" and include "tool_category",
"error_class", a truncated/shortened "error_message", and the required
privacy-safe "input_signature" field; also note that arguments may be included
but must be masked (no raw values or credentials). Ensure the wording mirrors
the suggested phrasing so the description lists tool_name/category, error_class,
truncated error_message, PII-safe input_signature, and optionally masked
arguments.

---

Outside diff comments:
In `@docs/docs/reference/telemetry.md`:
- Line 81: Update the sentence that currently reads "SQL queries or query
results" to clarify that raw SQL is not collected but PII-masked SQL (with
literals replaced by ?), such as the SQL included in sql_execute_failure events,
is collected for diagnostics; explicitly state "raw/unmasked SQL is never
collected; PII-masked SQL (literals replaced by '?') may be collected (e.g. in
sql_execute_failure events)" so the doc aligns with the recorded event behavior.

---

Nitpick comments:
In `@docs/docs/reference/telemetry.md`:
- Line 15: Update the `tool_call` table entry to mention the new
`input_signature` field added on failures: change the description for
`tool_call` to note that when a tool invocation fails it includes a PII-safe
`input_signature` (records only key names, value types, and lengths — not raw
values) so readers know failures include this privacy-preserving diagnostic
info; reference `tool_call` and `input_signature` in the updated sentence.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4d5b50d4-19cb-43fe-8b7d-c36efed548ff

📥 Commits

Reviewing files that changed from the base of the PR and between c95f7b3 and ead7a20.

📒 Files selected for processing (1)
  • docs/docs/reference/telemetry.md

@kulvirgit
Copy link
Collaborator

Multi-Model Code Review (7 AI models)

Verdict: APPROVE with 3 required fixes before merge

Reviewed by Claude, Codex (GPT-5.4), Grok, Kimi, MiniMax, GLM-5, Qwen. 1 convergence round.


MAJOR — Fix Before Merge

1. maskString PII leak — only masks single-quoted strings (all 7 models flagged, escalated during convergence)

  • telemetry/index.ts:456
  • Double-quoted strings ("John"), PostgreSQL dollar-quoted strings ($$secret$$) pass through unmasked into masked_sql, error_message, and masked_args fields.
  • Violates the privacy guarantees documented in telemetry.md.
  • Fix:
return s
  .replace(/'(?:[^'\\]|\\.)*'/g, "?")
  .replace(/"(?:[^"\\]|\\.)*"/g, "?")
  .replace(/\s+/g, " ")
  .trim()

2. ERROR_PATTERNS "connection" keyword is overly broad (5 models)

  • telemetry/index.ts:383
  • "connection" matches "connection established", "Invalid connection string" (should be "validation"). First-match-wins means misclassification.
  • Fix: Remove "connection" — the specific OS error codes (econnrefused, enotfound, econnreset, socket) already present are sufficient.

3. masked_sql is unbounded (Codex unique finding)

  • connections/register.ts:252
  • Unlike error_message (500 char cap) and masked_args (2000 char cap), masked_sql has no truncation. Large generated queries could exceed telemetry property limits.
  • Fix: Add .slice(0, 2000) before Telemetry.track().

MINOR — Follow-up PRs

4. detectQueryType doesn't handle SQL comments (Qwen)

  • Leading comments (-- comment\nSELECT...) cause misclassification as "OTHER".
  • Fix: Strip leading comments before prefix matching.

5. classifySkillSource uses fragile path matching (Qwen, MiniMax, Kimi, Codex)

  • includes("node_modules") and startsWith(os.homedir()) can misclassify. Projects under $HOME all classified as "global".

6. maskArgs/maskValue can crash on circular refs or BigInt (GLM-5, Kimi)

  • Recursive walking has no cycle detection. JSON.stringify throws on BigInt. Outer try/catch catches it but telemetry event is silently lost.

7. Validation failures never emit telemetry (Codex unique)

  • Telemetry wrapper starts after input.safeParse(args), so parse failures throw before any core_failure event.

8. Every soft failure emits core_failure (Codex unique)

  • metadata.success === false triggers core_failure, conflating expected tool-level negatives (missing files, non-zero bash exits) with actual internal failures. Pollutes the signal.

9. Missing tests for tool.ts telemetry hooks, sql_execute_failure, skill_used (Claude, Grok, MiniMax, Kimi, Qwen)


Positive Observations

  • Excellent PII protection design: computeInputSignature captures type shapes without values
  • All telemetry wrapped in try/catch — never breaks tool execution
  • 312 new test lines covering classifyError, masking, privacy guarantees
  • Clean 33-event taxonomy with snake_case naming
  • Machine ID is random UUID, email is SHA-256 hashed
  • File tool success events skipped (high volume, low signal)
  • Idempotent init with deduplication prevents race conditions

🤖 Multi-model review by 7 AI models with structured convergence. Session artifacts

- Extend `maskString` to also mask double-quoted strings (`"John"`, `$$secret$$`-adjacent) — single-quoted-only regex was flagged as PII leak
- Keep `connection` in `ERROR_PATTERNS` keywords (broad but intentional)
- Truncate `masked_sql` to 2000 chars before sending — was unbounded unlike `error_message` (500) and `masked_args` (2000)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/opencode/src/altimate/native/connections/register.ts (1)

258-258: Remove redundant type assertion on return value.

The object already conforms to SqlExecuteResult (error is optional there), so the cast can be dropped to keep type safety strict.

Small cleanup
-    return { columns: [], rows: [], row_count: 0, truncated: false, error: errorMsg } as SqlExecuteResult & { error: string }
+    return { columns: [], rows: [], row_count: 0, truncated: false, error: errorMsg }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/altimate/native/connections/register.ts` at line 258,
The return expression currently uses a redundant type assertion "as
SqlExecuteResult & { error: string }" when returning { columns: [], rows: [],
row_count: 0, truncated: false, error: errorMsg } — remove the cast so the
function returns the plain object (which already satisfies SqlExecuteResult with
optional error) and keep the rest of the logic unchanged; look for the return in
register.ts (the failing return expression) and simply drop the "as ..."
assertion to restore strict typing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/altimate/native/connections/register.ts`:
- Line 232: maskedErrorMsg and masked_sql rely on Telemetry.maskString which
currently doesn't redact PostgreSQL dollar-quoted literals, so update
Telemetry.maskString to recognize and redact dollar-quoted literal syntax
($tag$...$tag$ and $$...$$) in addition to single/double-quoted strings, then
re-run masking where maskedErrorMsg and masked_sql are produced (references:
maskedErrorMsg in register.ts and masked_sql in the same file) to ensure those
values never contain raw dollar-quoted content; implement the change inside
Telemetry.maskString (or a helper it calls) to detect dollar-quote boundaries,
replace contents with a fixed mask (respecting the existing max length
truncation), and add unit tests covering tagged and untagged dollar-quoted
cases.

---

Nitpick comments:
In `@packages/opencode/src/altimate/native/connections/register.ts`:
- Line 258: The return expression currently uses a redundant type assertion "as
SqlExecuteResult & { error: string }" when returning { columns: [], rows: [],
row_count: 0, truncated: false, error: errorMsg } — remove the cast so the
function returns the plain object (which already satisfies SqlExecuteResult with
optional error) and keep the rest of the logic unchanged; look for the return in
register.ts (the failing return expression) and simply drop the "as ..."
assertion to restore strict typing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 68594730-a813-4b58-af5d-c9af336b8ceb

📥 Commits

Reviewing files that changed from the base of the PR and between ead7a20 and 0a9c433.

📒 Files selected for processing (2)
  • packages/opencode/src/altimate/native/connections/register.ts
  • packages/opencode/src/altimate/telemetry/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opencode/src/altimate/telemetry/index.ts

suryaiyer95 and others added 2 commits March 18, 2026 21:26
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap all telemetry additions in `packages/opencode/src/tool/tool.ts`
and `packages/opencode/src/tool/skill.ts` with `// altimate_change
start/end` markers so the upstream marker-guard CI passes.

- `tool.ts`: markers around `import { Telemetry }` and the full
  telemetry instrumentation block (startTime through soft-failure
  core_failure emission)
- `skill.ts`: markers around `classifySkillSource` helper, `startTime`
  declaration, and the `Telemetry.track` try-catch for `skill_used`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dev-punia-altimate
Copy link

✅ Tests — All Passed

TypeScript — passed

cc @suryaiyer95
Tested at 47452978 | Run log | Powered by QA Autopilot

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/tool/tool.ts`:
- Around line 73-74: The telemetry wrapper that records startTime and emits
"tool_call" / "core_failure" is introduced too late (startTime is set at line
73) so exceptions thrown earlier by the schema/argument validation bypass
telemetry; move the telemetry wrapper (the code that records startTime and wraps
execution to emit "tool_call" and on-error "core_failure") to wrap the
validation step as well—i.e., initialize startTime and enter the try/catch
before the validation runs—or alternatively, inside the validation's catch block
emit the same "tool_call" and "core_failure" events (including error details and
elapsed time using startTime) before rethrowing so schema validation failures
are reported consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3310371d-74b5-4566-bd96-4ce9a09e6e38

📥 Commits

Reviewing files that changed from the base of the PR and between 0a9c433 and 39462c0.

📒 Files selected for processing (3)
  • docs/docs/reference/telemetry.md
  • packages/opencode/src/tool/skill.ts
  • packages/opencode/src/tool/tool.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/opencode/src/tool/skill.ts
  • docs/docs/reference/telemetry.md

Comment on lines +73 to +74
// altimate_change start — telemetry instrumentation for tool execution
const startTime = Date.now()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Schema validation failures still bypass failure telemetry.

Line 63 can throw before this new wrapper starts, so invalid-argument calls skip both tool_call and core_failure. That leaves model/schema mismatches out of the new failure signal. Please move the telemetry wrapper above validation, or emit the same failure events from the validation catch before rethrowing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/tool/tool.ts` around lines 73 - 74, The telemetry
wrapper that records startTime and emits "tool_call" / "core_failure" is
introduced too late (startTime is set at line 73) so exceptions thrown earlier
by the schema/argument validation bypass telemetry; move the telemetry wrapper
(the code that records startTime and wraps execution to emit "tool_call" and
on-error "core_failure") to wrap the validation step as well—i.e., initialize
startTime and enter the try/catch before the validation runs—or alternatively,
inside the validation's catch block emit the same "tool_call" and "core_failure"
events (including error details and elapsed time using startTime) before
rethrowing so schema validation failures are reported consistently.

@suryaiyer95 suryaiyer95 merged commit 9aa1d39 into main Mar 19, 2026
12 checks passed
@anandgupta42 anandgupta42 deleted the feat/core-failure-telemetry branch March 20, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants