The rule shape-checked a matcher as though it had to look like mcp__server__tool, so it reported working regexes as never firing and accepted patterns that fire on nothing. A user obeying it replaced a working matcher with a dead one — the failure the rule exists to prevent, reached by complying with it. Semantics were measured against the real CLI rather than inferred, and the reproduction ships as tools/measure-hook-matcher-semantics.mjs: a matcher with no metacharacter is compared by string equality, one with metacharacters is an unanchored regex. Both contested rows were confirmed live against an MCP server connected under two namings. A literal keeps the shape check. A pattern is compiled and tested against probes covering the server namings that actually occur, including an underscore inside the server segment and a hyphenated uuid, plus segments derived positionally from the matcher itself so a deliberately scoped mcp__memory__.* stays clean. Firing on some names but not others is now its own finding that names the missed probes and never says never fires. An uncompilable regex is its own finding rather than silently valid. The suggestion can no longer recurse: a recovered server segment must be name-shaped, and a property test asserts every suggestion satisfies the rule that produced it. Fixes #131
tools/ — human-run maintenance scripts (never in CI)
Occasional scripts a maintainer runs by hand — network I/O (cloning repos),
breadth sweeps, asset generation. They are NOT part of the shipped library: not
src/, not compiled to dist/, not tested, never run in CI. Run them from the
repo root. (The BUILD pipeline — api-extractor.mjs, build-report.mjs — lives in
scripts/, not here; tools/ is only the human-run stuff.)
Live — dogfood-corpus maintenance
refresh-vendor.sh— re-fetch + re-pin the SHA-pinned vendored plugin snapshots undertest/dogfood/. Run when: bumping a vendored plugin to a newer upstream commit. Seeresearch/dogfood-corpus.md.dogfood-sweep.sh— runvigiles auditacross a pinned list of real OSS Claude Code plugins and tally what the detectors find. Run when: before a release or after a detector change, to prove no false-positive regression on real plugins (breadth, vs the few SHA-pinned slices asserted in tests).
Live — harness ground truth
measure-hook-matcher-semantics.mjs— measure how the harness ACTUALLY matches a hookmatcher(literal equality vs unanchored regex; which MCP patterns fire on which server naming), by running the realclaudeCLI against the scripted mock model with one hook per row and a marker file as the oracle. No API key, no cost. Run when: a new Claude Code version lands, or before changingsrc/core/hook-matcher.ts— that detector encodes this table, and issue #131 is what happens when it is assumed instead of measured. Usage:node tools/measure-hook-matcher-semantics.mjs [--suite=builtin|mcp] [--server=<name>].
Occasional — pre-launch
fp-sweep.sh— launch-readiness "don't cry wolf" sweep: clone popular plugins/marketplaces, runvigiles audit, surface any high-precision rule flag as a false-positive candidate to triage. Run when: pre-launch FP triage.
Demo assets — for the UNBUILT "polished demo" (roadmap)
-
demo.sh— record an asciinema cast ofvigiles lintcatching stale references (asciinema rec --command "bash tools/demo.sh" vigiles.cast). -
make-demo-gif.py— generate an animated terminal GIF (Pillow).⚠️ Status: both feed the roadmap item "Build the ONE polished front-door demo," which is not built yet. The old
vigiles-demo.gifwas removed as unreferenced, so their output is currently unused. Kept as the tooling for that item — delete if the demo direction is dropped.
Not skills — on purpose
A tools/ script is deterministic automation; a skill is a model procedure with
judgment, so these are not skills. The two with real judgment on their output
(fp-sweep triage, dogfood-sweep regression summary) are a roadmap candidate to
wrap as .claude/skills/ contributor skills at launch — the skill would invoke
the script and reason about the result. refresh-vendor / demo.sh /
make-demo-gif.py stay plain scripts (mechanical or interactive, no judgment).