Skip to content

feat(autofixer): per-suggestion suppression via svelte-mcp-ignore#214

Open
coyotte508 wants to merge 5 commits into
sveltejs:mainfrom
coyotte508:mcp-ignore-suggestions
Open

feat(autofixer): per-suggestion suppression via svelte-mcp-ignore#214
coyotte508 wants to merge 5 commits into
sveltejs:mainfrom
coyotte508:mcp-ignore-suggestions

Conversation

@coyotte508
Copy link
Copy Markdown

@coyotte508 coyotte508 commented May 19, 2026

There are three kind of warnings:

  • eslint
  • svelte-compliler
  • custom (for this mcp)

The first two can already be ignored, the third not. This PR adds that (especially for some of the $effect warnings)

// svelte-mcp-ignore effect_calls_function
fetch_data();

<!-- svelte-mcp-ignore bind_this_attachment -->
<canvas bind:this={canvas}></canvas>

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

coyotte508 and others added 4 commits May 19, 2026 13:44
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>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

@coyotte508 is attempting to deploy a commit to the Svelte Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 19, 2026

🦋 Changeset detected

Latest commit: b5d68c9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/mcp Minor

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

@svelte-docs-bot
Copy link
Copy Markdown
Contributor

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>
@coyotte508 coyotte508 marked this pull request as ready for review May 19, 2026 12:07
@paoloricciuti
Copy link
Copy Markdown
Member

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 🤔

@coyotte508
Copy link
Copy Markdown
Author

well I'd like to be able to tell the AI to ignore specific warnings in specific places in my code 🤔

@paoloricciuti
Copy link
Copy Markdown
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants