vercel / vercel/vercel-plugin

posttooluse-validate: regex matches fire inside JSDoc and line comments — false positives on documentation prose

Open
#59 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
287
Forks
58
Avg merge
1d 1h
Merged PRs (30d)
17

Description

TL;DR

hooks/posttooluse-validate.mjs applies validation regexes line-by-line without first stripping comment ranges. Any matching phrase inside a /** */ JSDoc block, /* */ block comment, or // line comment fires a validator error, pointing at a line number inside the comment even though the actual code is correct.

Plugin version: 0.24.0.

Concrete example

// src/lib/supabase/server.ts

/**
 * Server-side Supabase client factory.
 *
 * Note: cookies() is async in Next 16 — we await it below.
 */
import { cookies } from 'next/headers'

export async function createServerSupabaseClient() {
  const cookieStore = await cookies()  // line 12 — correct usage
  // ...
}

Validator output (observed repeatedly in a real Next.js 16 + Supabase session):

❌ posttooluse-validate error:
  src/lib/supabase/server.ts:5 — "cookies() is async — use await"

Line 5 is inside the JSDoc block. Line 12 has the correct await cookies() call. The validator's regex matched the JSDoc phrase "cookies() is async" and emitted a false error.

Three distinct repeats in one 3-hour session. All three times the operator had to manually check the actual code before dismissing the error. Trust in the validator dropped significantly — which is especially damaging because #38 already conditions the operator to suspect plugin output, so real validator hits also get dismissed.

Where

hooks/posttooluse-validate.mjs lines ~216-233 iterate source lines and apply validation regexes per-line. The matcher has no awareness of comment ranges.

Proposed fix

Before applying line-based regexes in the validation loop, strip:

  1. Block comments /* ... */ (including JSDoc /** ... */). Multi-line-aware.
  2. Line comments // ... (from // to end of line).
  3. String literals — lower priority, causes a different class of false positives but same shape.

Options for implementation, in order of complexity:

  1. Preprocess with a lightweight regex-based comment stripper — applied once per file before the line iteration. Fast, good-enough for TypeScript/JavaScript. Handles ~95% of cases.
  2. Lightweight tokenizer — something like a minimal ts lexer that emits {kind, start, end} ranges. Excludes comment and string ranges from regex matching. More correct.
  3. Compile file with esbuild/ts-morph once per Write — strictly correct but adds dependency weight and latency. Probably overkill.

Option 1 is likely the right trade-off for a hook that fires on every Write/Edit.

Reproducer

// File: src/test.ts

/**
 * cookies() is async — this is documentation, not code.
 */

// `cookies()` is async — another documentation comment
const x = 1

Run a Write or Edit through Claude Code against this file. Validator will fire "cookies() is async" error on the JSDoc line and/or the line-comment line, even though no actual cookies() call exists.

Severity

High — a validator that fires errors on documentation prose degrades operator trust in the real errors. Combined with #38 (skill-injection noise), the compound effect is that operators disable or ignore the plugin entirely, losing the real value it provides.

Related

  • #38 — architectural: project context is advisory, not authoritative. Both issues compound — skill injection noise + validator false positives → operator tunes out all plugin output.
  • #51matchPromptWithReason uses unbounded .includes() for phrase matching. Same class of bug (regex/substring matching without awareness of surrounding context).
  • Companion issue I'm about to file: model-slug validator flags Anthropic canonical hyphen slugs (claude-opus-4-7) as typos expecting dots. Will link here when filed.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in hooks/posttooluse-validate.mjs around lines 216-233, where source lines are iterated and validation regexes are applied. Reproduce the false positive with the provided src/test.ts example, then verify that block and line comments no longer trigger validators while real code still does. String literals are a lower-priority follow-up noted in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.