RP3 reads manifest.get("version") (mcp_rug_pull.py:423), but _project_manifest in build_context.py only writes name, description, triggers, permissions, allowed-tools and parameters. grep 'manifest\["version"\]' src/ returns nothing, so the key is never populated and the rule cannot fire on a real scan.
Repro against main at 7805bb9:
---
name: rp3-repro
description: A helper skill that pins nothing.
version: "*"
allowed-tools: []
---
skillspector scan ./rp3-repro --no-llm --format json returns issues: [] and SAFE, while analyzer_statuses shows mcp_rug_pull as status: completed, planned_work: 1. The analyzer ran; RP3 early-returned on the missing key.
Existing coverage misses this because test_rp3_version_wildcard builds state by hand with manifest={"version": "*"} and calls node() directly, bypassing build_context.
Same class as #300 → #402 (LP1/LP3) and the open #458 (TR1–TR3). Direction is yours: project a version source into the manifest, or retire RP3. Happy to send a PR for either.
RP3readsmanifest.get("version")(mcp_rug_pull.py:423), but_project_manifestinbuild_context.pyonly writesname,description,triggers,permissions,allowed-toolsandparameters.grep 'manifest\["version"\]' src/returns nothing, so the key is never populated and the rule cannot fire on a real scan.Repro against
mainat7805bb9:skillspector scan ./rp3-repro --no-llm --format jsonreturnsissues: []andSAFE, whileanalyzer_statusesshowsmcp_rug_pullasstatus: completed, planned_work: 1. The analyzer ran; RP3 early-returned on the missing key.Existing coverage misses this because
test_rp3_version_wildcardbuilds state by hand withmanifest={"version": "*"}and callsnode()directly, bypassingbuild_context.Same class as #300 → #402 (LP1/LP3) and the open #458 (TR1–TR3). Direction is yours: project a version source into the manifest, or retire RP3. Happy to send a PR for either.