azure/audit-filters
Analyze feedback and memories to suggest filter.yaml additions, then open a PR. Use for: audit filters, analyze feedback for filters, suggest filters, update filters, filter additions, feedback analysis, bad comments analysis, add filter rules, filter PR.
npx skills add https://github.com/Azure/azure-sdk-tools --skill audit-filters
filter.yaml exception rules for a language based on feedback themesThis is a multi-phase workflow:
IsGeneric status; identify recurring bad-comment patternsDO NOT ... lines for metadata/{lang}/filter.yamlUnless the user says otherwise, always apply these defaults:
productionbad and delete feedback (exclude good)Map the user's language name to the metadata directory name:
| User says | {lang} directory | --language flag value |
|-----------|---------------------|------------------------|
| Java | java | java |
| C# / .NET / dotnet | dotnet | dotnet |
| Python | python | python |
| TypeScript / JavaScript | typescript | typescript |
| Go / Golang | golang | golang |
| Swift / iOS | ios | ios |
| Android | android | android |
| C / C++ / Clang | clang | clang |
| Rust | rust | rust |
The user will typically specify a calendar month by name (e.g. "March", "January 2025"). Resolve to the full month date range:
| User says | start_date | end_date |
|-----------|-----------|----------|
| "March" (current year) | YYYY-03-01 | YYYY-03-31 |
| "January 2025" | 2025-01-01 | 2025-01-31 |
| "March 1 to March 15" | YYYY-03-01 | YYYY-03-15 |
When only a month name is given without a year, use the current year. Be careful with month lengths (28/29/30/31 days).
Run both commands sequentially in the same foreground terminal. Use a 120-second timeout for each.
New-Item -ItemType Directory -Path output -Force | Out-Null; if (Test-Path output/feedback_output.json) { Remove-Item output/feedback_output.json }; python cli.py report feedback -s <start_date> -e <end_date> -l <language> --exclude good --include-implicit | Out-File -Encoding UTF8 output/feedback_output.json
if (Test-Path output/memory_output.json) { Remove-Item output/memory_output.json }; python cli.py report memory -s <start_date> -e <end_date> -l <language> | Out-File -Encoding UTF8 output/memory_output.json
After both commands complete, read both output files with read_file.
Read the current filter file at metadata/{lang}/filter.yaml so you know what rules already exist.
Then analyze the collected feedback and memories. Produce a summary organized as follows:
By Feedback Reason — Group comments by their Feedback[].Reasons values (e.g. AcceptedRenderingChoice, FactuallyIncorrect, RenderingBug, NotRelevant, TooNitpicky, Other). For each reason, count occurrences and list representative CommentText excerpts.
By Theme — Identify recurring themes across the bad comments. A theme is a pattern you can describe in one sentence (e.g. "commenting on interface method implementations", "suggesting consolidating overloads"). Include the count of comments matching each theme.
By IsGeneric Status — Report how many bad comments had IsGeneric: true vs false. Generic comments are not tied to a specific guideline and are more likely candidates for filter rules.
By Submitter — Note which users (Feedback[].SubmittedBy) provided the most feedback. The most significant contributor will be used as the PR assignee.
Cross-reference with Memories — Check if any memories (especially those with is_exception: true) suggest filter rules that are not yet in filter.yaml.
Present this analysis to the user in a clear summary table or grouped list.
Based on the analysis, propose specific new lines to add to metadata/{lang}/filter.yaml. Each recommendation must:
N. DO NOT <description>filter.yaml. If an existing rule already covers the same behavior (even with different wording), do NOT propose it again. Explain in the analysis that the theme was already covered and cite the existing rule number.When presenting recommendations, clearly label each with its signal strength:
is_exception: trueDo NOT automatically exclude low-signal items. Present ALL actionable patterns to the user with their signal strength clearly marked, and let the user (or reviewer) decide whether to include them in the PR.
Present the recommendations in a numbered list, each with:
IsGeneric or guideline-linkedExample recommendation format:
> Proposed rule 8: DO NOT comment on explicit interface implementations for serialization (IJsonModel, IPersistableModel)
> - Evidence: 4 bad comments with reason FactuallyIncorrect, all IsGeneric: true
> - Example: *"Interface method implementation for AzureAISearchIndex is unexpected here"*
Use the vscode_askQuestions tool to present the user with a selection:
"Confirm filter PR""Here are the proposed filter additions for {lang}. Should I create a PR with these changes?""Yes, all of them" (recommended)"Yes, but only specific ones (let me pick)""No, skip the PR"If the user selects specific ones, note which rule numbers to include.
If the user says no, stop here.
gh api user --jq .login
Store this as {current_user}.
The reviewer should be the feedback submitter (Feedback[].SubmittedBy) who appears most frequently in the bad/deleted comments that led to the filter additions. If there is a tie, pick the one whose feedback is most relevant to the proposed rules.
Store this as {top_submitter}.
Generate a branch name: avc/update-{lang}-filter-{YYYYMMDD} (using today's date).
The branch MUST be based on origin/main so the PR contains only the filter.yaml change. Do NOT branch from the current working branch — it may contain unrelated changes.
git fetch origin main; git checkout -b avc/update-{lang}-filter-{YYYYMMDD} origin/main
If origin/main fails (e.g. main is in another worktree), use FETCH_HEAD:
git fetch origin main; git checkout -b avc/update-{lang}-filter-{YYYYMMDD} FETCH_HEAD
Edit metadata/{lang}/filter.yaml to append the confirmed rules. Use sequential numbering continuing from the last existing rule. Maintain the existing indentation (2-space indent under the YAML block scalar exceptions: |).
Stage only the filter file — never use git add . or git add -A:
git add metadata/{lang}/filter.yaml; git commit -m "[AVC] Update {lang} filter based on {month} {year} feedback"
Before pushing, verify the commit contains exactly 1 file:
git diff --stat origin/main..HEAD
If more than 1 file appears, STOP and fix the branch before pushing. Only after confirming 1 file changed:
git push origin avc/update-{lang}-filter-{YYYYMMDD}
gh pr create --repo Azure/azure-sdk-tools --title "[AVC] Update {lang} filter" --body "Filter additions based on a review of feedback collected during {timespan}." --label "APIView Copilot" --assignee {current_user} --reviewer {top_submitter} --base main
Where:
{lang} — The language name (e.g. java, dotnet, python){timespan} — The human-readable date range (e.g. "March 2026", "January 1 – January 15, 2025"){current_user} — The GitHub handle of the person running the skill (PR assignee){top_submitter} — The GitHub handle of the most significant feedback contributor (PR reviewer)After the PR is created, report the PR URL to the user.
python cli.py not .\avc: The avc.bat script may resolve to system Python.2>&1: Merges stderr into stdout, corrupting JSON. Only redirect stdout.>: Produces UTF-16 in PowerShell 5.1. Use | Out-File -Encoding UTF8.read_file rather than relying on terminal output.filter.yaml before proposing additions to avoid duplicates.-2).origin/main, never from the current working branch. The working branch may contain dozens of unrelated changes that will pollute the PR. Verify with git diff --stat origin/main..HEAD before pushing.APIView Copilot label must already exist in the repo. If gh pr create fails on the label, omit --label and add the label manually after creation.gh pr create fails on an assignee, omit that assignee and note it in the PR body instead.Take azure/audit-filters from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.