svg-add-primitive — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited svg-add-primitive (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are extending the system's vocabulary. A new primitive is a long-term commitment — once shipped, presets will depend on it. Your job is to ship it correctly the first time, not to ship it fast.
$ARGUMENTS is the primitive's category-qualified name (e.g., motion.createOrbit, shapes.createStar, filters.createTurbulence). If the argument is missing or unparseable, stop and ask the calling thread to clarify with format <category>.<name>.
Without a gatekept extension path, lib/primitives/ quickly accumulates inconsistent signatures, undocumented functions, and primitives used by no one. The discipline below is what makes the library compound rather than sprawl. See D:\github_repository\svg-animation-studio\docs\extension-protocol.md for the rationale.
Before adding to lib/primitives/<category>.js, read the whole file. Match:
create<Verb> for actions (createJump), create<Noun> forstatic elements (createMusicalNote).
motion.* → { css: string, className: string }shapes.* → raw SVG element stringfilters.* → <filter> element stringopts = {} object; destructure with defaults atthe top; never positional args.
motion.* uses uniqueId(prefix) and includes theclassName in the keyframe name to avoid collisions. shapes.* and filters.* accept id from the caller.
compose() callsmotion.resetIdCounter() at start.
Add the new function to lib/primitives/<category>.js and to its module.exports. Include a 1-line JSDoc above the function explaining what motion / shape / filter it produces and what the key params control. Do not pad the JSDoc with @param lines for every option — the lib-api.md table is the contract for that.
Example skeleton (motion):
/** Orbital sweep: an element traces a circle around a center point. */
function createOrbit(opts = {}) {
const {
duration = '4s', easing = 'linear',
radius = 20, centerX = 0, centerY = 0,
direction = 'cw'
} = opts;
const cls = uniqueId('cv-orbit');
const kf = `kf-${cls}`;
const sign = direction === 'cw' ? 1 : -1;
const css = `.${cls} {
animation: ${kf} ${duration} ${cssEasing[easing]} infinite;
transform-origin: ${centerX}px ${centerY}px;
}
@keyframes ${kf} {
0% { transform: rotate(0deg) translateX(${radius}px) rotate(0deg); }
100% { transform: rotate(${sign * 360}deg) translateX(${radius}px) rotate(${-sign * 360}deg); }
}`;
return { css, className: cls };
}A primitive that no preset uses is unverified vocabulary. Pick an existing preset that legitimately needs the new primitive, OR — if the user is adding the primitive for a brand-new animation — make sure they're about to write that preset.
If no preset will use it within this session, stop and report:
Need primitive<name>but no consuming preset is being built. Either wait until building one needs it, or write a placeholder preset that demonstrates the primitive (recommended: name it<name>-demo).
npm testThree outcomes:
signature used elsewhere, or the export order in module.exports shifted something. Re-examine your diff. If the change is intentional, run npm run snapshot:update AND in your final report flag every affected preset so the caller does a visual recheck.
Fix before proceeding.
Two files MUST be updated:
docs/lib-api.md — add an H3 section under the right category with:CLAUDE.md — add a one-line entry under lib/primitives/<category>.jsin the "lib API index" section. Format: - \createOrbit\ — orbital sweep around a center point
Increment the count in CLAUDE.md (e.g., "(10)" → "(11)").
Return a one-block report. Keep it short.
EXTENDED: motion.createOrbit
Signature: createOrbit({ duration, easing, radius, centerX, centerY, direction })
Used by: <preset slug>
Tests: <pass | updated snapshots: list>
Docs: docs/lib-api.md, CLAUDE.mdlib/primitives/*.js for any reason other than this skill.future sessions and rot quickly.
opts object.module.exports — the function exists in memory but no one canuse it.
npm run snapshot:update without explicit reason. Snapshots thatsilently change are bug seeds.
If motion, shapes, filters doesn't seem right — stop and propose a new category. This is rare (we've seen easing cover one edge case). Adding a fourth category is a design decision, not a routine extension. Ask the calling thread before proceeding.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.