feat(autofixer): per-suggestion suppression via svelte-mcp-ignore#214
feat(autofixer): per-suggestion suppression via svelte-mcp-ignore#214coyotte508 wants to merge 5 commits into
svelte-mcp-ignore#214Conversation
The custom-visitor pass (`add_autofixers_issues`, the third source after
the Svelte compiler and ESLint passes) had no ignore protocol. Some
visitors are deliberately heuristic — they nudge toward Svelte 5 idioms
but can fire on intentional code (an `$effect` whose side effect into a
third-party library cannot become a `$derived`, a `bind:this` on a host
element where an attachment would be a wider refactor than worth, etc.).
This commit adds a directive comment that silences a single suggestion
on the following line, modelled after `svelte-ignore` and
`eslint-disable-next-line`:
// svelte-mcp-ignore effect_calls_function
fetch_data();
<!-- svelte-mcp-ignore bind_this_attachment -->
<canvas bind:this={canvas}></canvas>
Each visitor suggestion now carries a stable lowercase snake_case code
(`effect_calls_function`, `effect_assigns_state`, `bind_this_attachment`,
`use_action_attachment`, `derived_with_function`, `imported_runes`,
`runes_instead_of_store`, `wrong_property_access_state`). Multiple codes
can be listed on one directive (space-separated). Stale codes (no
matching suggestion fired) and typos (unknown code) surface as follow-up
"unused directive" suggestions so the comments don't quietly rot.
Implementation lives in a single new module
(`autofixers/ignore-directives.ts`) that collects directives by target
line once per file. Visitors call `push_suggestion(state.output,
state.ignore_registry, code, node.loc?.start?.line, message)` instead of
`state.output.suggestions.push(message)`. `read-state-with-dollar.ts`
remains un-guarded because its diagnostics are `issues` (hard errors),
not `suggestions`.
Scope matches `svelte-ignore`: a directive on line N silences suggestions
whose triggering node starts on line N+1. This means two statements that
share a target line can be silenced by one directive, but two statements
on different lines need two directives — same shape the Svelte compiler
warning suppression already uses.
Tests:
- 14 new test cases in `ignore-directives.test.ts` covering every code,
the `//` / `/* */` / `<!-- -->` comment shapes, the line-N-only scope,
multiple-codes-per-directive, the unused-directive diagnostic, and the
unknown-code diagnostic.
- All 251 pre-existing tests still pass (the refactor is non-breaking;
`add_autofixers_issues` builds its own registry when invoked at the top
level).
Docs:
- `documentation/docs/30-mcp/40-tools.md`: user-facing "Suppressing
suggestions" section + code table.
- `tools/instructions/AGENTS.md`: instruction for the LLM that drives
the autofixer.
- `CLAUDE.md`: developer note pointing at the new module.
- Tool description on `svelte-autofixer` itself updated so any LLM
introspecting the tool registration sees the directive shape.
Co-authored-by: Cursor <cursoragent@cursor.com>
…face Distributed copies of the source docs needed regeneration so the directive shows up in every place an LLM might consult: - `svelte-task` MCP prompt body — clients invoking the prompt get the directive in their system instruction. - `documentation/docs/30-mcp/.generated/prompts.md` — generated from `svelte-task.ts` (also picks up an unrelated section-list refresh the regenerator was carrying since the previous run; one-time noise, not a behavioural change). - `documentation/docs/20-instructions/.generated/agents.md` and `packages/opencode/instructions/opencode-agents.md` — regenerated from `tools/instructions/AGENTS.md` via `sync-opencode-plugin.ts`. - `plugins/cursor/svelte/rules/svelte-mcp-tools.mdc` and `plugins/cursor/svelte/.cursor-plugin/plugin.json` — regenerated by `sync-cursor-plugin.ts`; the plugin.json bump is the auto-applied patch version bump from `bump-plugin-versions.ts`. No source-of-truth changes apart from the one sentence added to `svelte-task.ts`. Run via the existing repo scripts: `pnpm sync-plugins && pnpm generate-prompt-docs && pnpm generate-skill-docs && pnpm generate-subagent-docs`. Co-authored-by: Cursor <cursoragent@cursor.com>
…ill workflow
The skill's Workflow checklist now has a step 4 explaining when to
reach for a directive (confirmed false positive — examples: $effect
imperatively pushing into a third-party library, bind:this whose
attachment refactor is wider than the change at hand) and listing the
eight available codes. Same content as the docs site / AGENTS.md, just
surfaced where an LLM that loaded this skill would actually consult.
Regenerates the distributed copies under
`plugins/{cursor,claude}/svelte/skills/`,
`packages/opencode/skills/`, and
`documentation/docs/40-skills/.generated/skills.md` via the existing
sync scripts.
Co-authored-by: Cursor <cursoragent@cursor.com>
Each visitor suggestion now carries a trailing ` [<code>]` marker
(e.g. `… [effect_calls_function]`) so an LLM consumer can read the
suggestion and write the matching `svelte-mcp-ignore` directive
without consulting any external docs surface. The marker is added by
`push_suggestion` in one place; visitors are unchanged.
Test fallout: `add-autofixers-issues.test.ts` and
`ignore-directives.test.ts` use a `run()` helper that strips the
marker before returning, so all 233 + 11 existing assertions match the
human-readable message text unchanged. Three new tests assert the
marker shape directly via a `run_raw()` sibling helper.
Doc tightening (the marker makes most of the inline code lists
redundant):
- `svelte-autofixer` tool description: drop the inline enumeration of
all eight codes. Mention the directive in one line.
- `svelte-task` MCP prompt body: collapse the suppression instruction
to one sentence — the prompt runs per task and every token counts.
- `tools/instructions/AGENTS.md`: same — one sentence.
- `svelte-code-writer` SKILL.md step 4: drop the inline code list,
point at the autofixer's own unknown-code reply.
- `documentation/docs/30-mcp/40-tools.md`: keep the human-facing code
table (it's the only place a human looking up codes goes) but
shorten the surrounding prose.
Distributed copies under `plugins/{cursor,claude,opencode}/` and
`documentation/docs/.../.generated/` regenerated via
`pnpm sync-plugins && pnpm generate-{skill,prompt,subagent}-docs`.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
@coyotte508 is attempting to deploy a commit to the Svelte Team on Vercel. A member of the Team first needs to authorize it. |
🦋 Changeset detectedLatest commit: b5d68c9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
With the `[<code>]` marker on every suggestion, an LLM consumer never needs to learn codes via the typo-recovery loop — it reads them inline from the autofixer's reply. The instruction surfaces (`AGENTS.md`, the `svelte-code-writer` SKILL.md step 4) drop the unused-directive footnote. The human-facing `documentation/docs/30-mcp/40-tools.md` page still mentions stale/typo reporting; that's a documentation surface, not an operational instruction. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Mmm this is an interesting problem... I'm not sure we want to give the AI an easy way out of the fixes. I'll need to think about how we could approach this 🤔 |
|
well I'd like to be able to tell the AI to ignore specific warnings in specific places in my code 🤔 |
I understand the use case, I'm just not sure this is the best way of doing that...I need to think about it |
There are three kind of warnings:
The first two can already be ignored, the third not. This PR adds that (especially for some of the
$effectwarnings)Context
I have a codebase with 17+ warnings from the autofixer that can't be ignored currently, mostly effect ones that are false positives
AI disclaimer
Done with Cursor + Claude Opus 4.7, gave it some instructions (less verbosity, adapt test runner helper to not rewrite 192 tests by needing to add the
[error-code]to them), tests added