$npx -y skills add Rune-kit/rune --skill hallucination-guardVerify AI-generated imports, API calls, and packages actually exist. Use when finishing AI-generated code that introduces new imports or external API calls — auto-fires after fix/cook to catch phantom functions, non-existent packages, and slopsquatting attacks.
| 1 | # hallucination-guard |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | Post-generation validation that verifies AI-generated code references actually exist. Catches the 42% of AI code that contains hallucinated imports, non-existent packages, phantom functions, and incorrect API signatures. Also defends against "slopsquatting" — where attackers register package names that AI commonly hallucinates. |
| 6 | |
| 7 | ## Triggers |
| 8 | |
| 9 | - Called by `cook` after code generation, before commit |
| 10 | - Called by `fix` after applying fixes |
| 11 | - Called by `preflight` as import verification sub-check |
| 12 | - Called by `review` during code review |
| 13 | - Auto-trigger: when new import statements are added to codebase |
| 14 | |
| 15 | ## Calls (outbound) |
| 16 | |
| 17 | # Exception: L3→L3 coordination |
| 18 | - `research` (L3): verify package existence on npm/pypi |
| 19 | |
| 20 | ## Called By (inbound) |
| 21 | |
| 22 | - `cook` (L1): after code generation, before commit |
| 23 | - `fix` (L2): after applying fixes |
| 24 | - `preflight` (L2): import verification sub-check |
| 25 | - `review` (L2): during code review |
| 26 | - `db` (L2): verify SQL syntax and ORM method calls are real |
| 27 | - `review-intake` (L2): verify imports in code submitted for review |
| 28 | - `skill-forge` (L2): verify imports in newly generated skill code |
| 29 | - `adversary` (L2): verify APIs/packages in plan actually exist |
| 30 | |
| 31 | ## Execution |
| 32 | |
| 33 | ### Step 1 — Extract imports |
| 34 | |
| 35 | Use `Grep` to find all import/require/use statements in changed files: |
| 36 | |
| 37 | ``` |
| 38 | Grep pattern: ^(import|require|use|from)\s |
| 39 | Files: changed files passed as input |
| 40 | Output mode: content |
| 41 | ``` |
| 42 | |
| 43 | Collect every imported module name and file path. Separate into: |
| 44 | - Internal imports (start with `./`, `../`, `@/`, `~/`) |
| 45 | - External packages (bare module names) |
| 46 | |
| 47 | ### Step 2 — Verify internal imports |
| 48 | |
| 49 | For each internal import path, use `Glob` to confirm the file exists in the codebase. |
| 50 | |
| 51 | ``` |
| 52 | Glob pattern: <resolved import path>.* (try .ts, .tsx, .js, .jsx, .py, .rs etc.) |
| 53 | ``` |
| 54 | |
| 55 | If `Glob` returns no results → mark as **BLOCK** (file does not exist). |
| 56 | |
| 57 | Also use `Grep` to verify that the specific exported name (function/class/const) exists in the resolved file: |
| 58 | |
| 59 | ``` |
| 60 | Grep pattern: export (function|class|const|default) <name> |
| 61 | File: resolved file path |
| 62 | ``` |
| 63 | |
| 64 | If export not found → mark as **WARN** (symbol may not be exported). |
| 65 | |
| 66 | ### Step 3 — Verify external packages (Dependency Check Before Import) |
| 67 | |
| 68 | > From taste-skill (Leonxlnx/taste-skill, 3.4k★): "Before importing ANY 3rd party lib, check package.json." |
| 69 | |
| 70 | Use `Read` on the project's dependency manifest to confirm each external package is listed: |
| 71 | |
| 72 | - JavaScript/TypeScript: `package.json` → check `dependencies` and `devDependencies` |
| 73 | - Python: `requirements.txt` or `pyproject.toml` → `[project.dependencies]` and `[project.optional-dependencies]` |
| 74 | - Rust: `Cargo.toml` → `[dependencies]` and `[dev-dependencies]` |
| 75 | |
| 76 | **Pre-import gate** (BEFORE writing import statements, not just after): |
| 77 | 1. If the agent is ABOUT to import a package → check manifest FIRST |
| 78 | 2. If package is NOT in manifest → output install command before writing the import: |
| 79 | ``` |
| 80 | ⚠ Package '<name>' not in dependencies. Install first: |
| 81 | npm install <name> # JS/TS |
| 82 | pip install <name> # Python |
| 83 | cargo add <name> # Rust |
| 84 | ``` |
| 85 | 3. If package IS in manifest → proceed with import |
| 86 | |
| 87 | **Post-import verification** (after code is written): |
| 88 | - If package is **not listed** in the manifest → mark as **BLOCK** (phantom dependency) |
| 89 | - If package is listed but not installed (no lockfile entry) → mark as **WARN** (not yet installed) |
| 90 | |
| 91 | Also check for typosquatting: if package name has edit distance ≤ 2 from a known popular package (axios/axois, lodash/lodahs, react/recat), mark as **SUSPICIOUS**. |
| 92 | |
| 93 | ### Step 3.5 — Slopsquatting Registry Verification |
| 94 | |
| 95 | <HARD-GATE> |
| 96 | Any NEW package added to the manifest (not previously in the lockfile) MUST be verified against the actual registry. |
| 97 | AI agents hallucinate package names at high rates. A package that doesn't exist on npm/PyPI/crates.io = supply chain risk. |
| 98 | </HARD-GATE> |
| 99 | |
| 100 | For each NEW external package (present in manifest but absent from lockfile): |
| 101 | |
| 102 | **3.5a. Registry existence check:** |
| 103 | ``` |
| 104 | JavaScript: Bash: npm view <package-name> version 2>/dev/null |
| 105 | Python: Bash: pip index versions <package-name> 2>/dev/null |
| 106 | Rust: Bash: cargo search <package-name> --limit 1 2>/dev/null |
| 107 | ``` |
| 108 | |
| 109 | If command returns empty/error → **BLOCK** (package does not exist on registry — likely hallucinated name). |
| 110 | |
| 111 | **3.5b. Popularity check (slopsquatting defense):** |
| 112 | ``` |
| 113 | JavaScript: Bash: npm view <package-name> 'dist-tags.latest' 'time.modified' 2>/dev/null |
| 114 | → If last modified > 2 years ago AND weekly downloads < 100: SUSPICIOUS |
| 115 | Python: Use rune:researc |