Skip to main content

fix-false-positives

Use when the user asks to "fix false positives", "check FP stats", "triage autofixer false positives", "why is rule X getting dismissed", or wants to reduce dismissal rates in the program_autofixer. Queries live dismissal telemetry from Databricks, ranks rules by false-positive burden, diagnoses the root cause in the rule's visitor, and implements a fix with the user approving each step.

Jump to install

Source facts

Repository
solana-foundation/solana-mcp-official
Last source activity
August 31, 2026 at 16:50
Detected SKILL.md language
English
Stars
81
Forks
22

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
fix-false-positives
description
Use when the user asks to "fix false positives", "check FP stats", "triage autofixer false positives", "why is rule X getting dismissed", or wants to reduce dismissal rates in the program_autofixer. Queries live dismissal telemetry from Databricks, ranks rules by false-positive burden, diagnoses the root cause in the rule's visitor, and implements a fix with the user approving each step.
user-invocable
true
# Fix autofixer false positives Reduce `program_autofixer` false positives using real dismissal telemetry. The model dismisses an issue when it verifies a `false_positive_hints` condition holds, so a high dismissal rate on a rule means that rule's analysis is missing something the model can see. This skill is a conversation, not a batch job. Never implement a fix the user has not approved, and never claim a root cause you have not confirmed by reading the rule source. ## 1. Fetch the stats Rank rules by dismissal burden over the last 90 days: ```sql WITH parsed AS ( SELECT from_json(response_text, 'rules array<string>, dismissed_rules array<string>') AS j FROM ${catalog}.${schema}.mcp_tool_calls WHERE tool_name = 'program_autofixer' AND row_type = 'response' AND timestamp >= current_timestamp() - INTERVAL 90 DAYS ), fires AS ( SELECT explode(j.rules) AS rule, 1 AS fired, 0 AS dismissed FROM parsed UNION ALL SELECT explode(j.dismissed_rules) AS rule, 0 AS fired, 1 AS dismissed FROM parsed ) SELECT rule, sum(fired) AS fires, sum(dismissed) AS dismissals, round(100.0 * sum(dismissed) / nullif(sum(fired), 0), 1) AS dismissal_pct FROM fires GROUP BY rule HAVING sum(fired) > 0 ORDER BY dismissals DESC LIMIT 20 ``` Use `mcp__databricks__execute_sql_read_only`. Substitute `${catalog}` and `${schema}` from the deployed bundle values for the `catalog` and `schema` variables declared in `databricks.yml`; they are intentionally not committed, so ask the user if you cannot resolve them. Note that `rules` is a distinct set per tool call, so `fires` counts calls where the rule appeared, not individual issues. Rank by absolute `dismissals`, not by percentage: a rule at 50% of 4 fires is noise, a rule at 20% of 800 fires is the real cost. Ignore rules under ~20 fires. The 90-day window spans past fixes. Check `git log --oneline -20 -- lib/tools/programAutofixer/visitors/` for rules already fixed; for those, re-run the query with a window starting after the fix deployed to see whether it actually worked, and tell the user the before/after. That is how the loop closes: a previous run's fix is graded at the start of the next run, not at the end of its own. Present the top rules to the user as a short table and ask which one to work on. Recommend one and say why. ## 2. Find which blind spot For the chosen rule, break dismissals down by which `false_positive_hints` index the model matched: ```sql WITH parsed AS ( SELECT from_json(response_text, 'dismissed_hint_counts map<string, map<string, int>>') AS j FROM ${catalog}.${schema}.mcp_tool_calls WHERE tool_name = 'program_autofixer' AND row_type = 'response' AND timestamp >= current_timestamp() - INTERVAL 90 DAYS ), hits AS (SELECT explode(j.dismissed_hint_counts) AS (rule, buckets) FROM parsed) SELECT rule, bucket, sum(n) AS dismissals FROM hits LATERAL VIEW explode(buckets) AS bucket, n WHERE rule = '<RULE>' GROUP BY rule, bucket ORDER BY dismissals DESC ``` Bucket keys are the hint index as a string, `'other'` when no listed hint matched, or `'unspecified'` when the caller omitted `matched_hint`. Map each index back to the hint text in the rule's visitor. These counts are per dismissed issue, while step 1 counts calls, so the buckets sum higher than the step 1 dismissal count. Compare buckets against each other, not against step 1. A large `other` bucket means the hints themselves are incomplete: the model is finding a blind spot nobody has written down. That is a different fix from a hint index dominating. Dismissal `reason` text and fingerprints are deliberately not logged, so the telemetry tells you *which* condition, never the specific code. Do not go looking for a raw reason column. ## 3. Diagnose Read the rule at `lib/tools/programAutofixer/visitors/<rule>.ts` and its `false_positive_hints`. Shared analysis lives in `_helpers.ts` and `_anchor-helpers.ts`; the walker and visitor context are in `walk.ts` and `handler.ts`. Common root causes seen so far: - **Scope too narrow.** Rule checks only the current function, but the verification lives in a caller, a helper, or elsewhere in the file. This was the `arbitrary-cpi` case (commit `9bbf0be`). - **Pattern too literal.** Rule matches one spelling of a safe construct and misses equivalent ones (builder chains, qualified paths, aliases). - **Missing framework knowledge.** Anchor constraint or macro already enforces the property, rule does not know about it. State the root cause to the user in a couple of sentences with the file:line evidence. If the telemetry and the source disagree, say so and stop rather than guessing. ## 4. Propose, then confirm Propose the narrowest fix that kills the identified bucket. Give the user: - what changes, in which file - roughly how many of the observed dismissals it should eliminate - what it deliberately does not cover - the false-negative risk: every FP fix widens what the rule accepts as safe, so name what a real attacker could now slip past Ask the user to approve, adjust, or reject before writing any code. If the fix would suppress a genuine vulnerability class, say that plainly and prefer rewording the hint over loosening the check. ## 5. Implement - Edit the rule (and helpers, if the analysis is shared). - Add fixtures to `tests/unit/programAutofixer/fixtures-anchor.ts` or `fixtures-pinocchio.ts` covering both directions: the FP pattern must stop firing, and a near-miss unsafe variant must still fire. - Run `pnpm test`. Report the real result; if anything fails, say so and fix it before continuing. - Update `false_positive_hints` if the fix makes a listed condition obsolete or reveals a new one. Show the user the diff and ask before committing. On approval, stage only the files the fix touched, never `git add -A`, and commit with a `fix(autofixer):` message describing the behavior change. Do not push or open a PR unless the user asks. Passing tests are not proof the fix worked; only telemetry is, and that arrives weeks later. Step 1 of the next run grades this one.
View on GitHub