From fa8f3897772368e62f5399c6f87574fca20b791f Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 3 Oct 2026 11:21:50 -0400 Subject: [PATCH 1/3] feat(animation): report a missing node once per session with a SessionStart node-notice row Co-Authored-By: Claude Opus 5.5 --- docs/skill-cheat-sheet.md | 1 + plugins/animation/.claude-plugin/plugin.json | 2 +- plugins/animation/CHANGELOG.md | 7 ++++ plugins/animation/README.md | 1 + plugins/animation/hooks/hooks.json | 6 +++ .../skills/check-prerequisites/SKILL.md | 38 +++++++++++++++++++ scripts/node-notice-rows.test.sh | 2 - scripts/skill-leaf-name-registry.txt | 7 ++-- 8 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 plugins/animation/skills/check-prerequisites/SKILL.md diff --git a/docs/skill-cheat-sheet.md b/docs/skill-cheat-sheet.md index 895f879fad..3f0457b9b7 100644 --- a/docs/skill-cheat-sheet.md +++ b/docs/skill-cheat-sheet.md @@ -181,6 +181,7 @@ owned by [docs/catalog-taxonomy.md](catalog-taxonomy.md). | [`/adhd:clarify`](../plugins/adhd/skills/clarify/SKILL.md) | `adhd` | Reshape a dense, decision-heavy message into clear one-decision-at-a-time chunks, losing nothing | | [`/adhd:shape`](../plugins/adhd/skills/shape/SKILL.md) | `adhd` | Set a standing action-first output posture. Lead with the next action, cut preamble | | [`/ai-slop:audit`](../plugins/ai-slop/skills/audit/SKILL.md) | `ai-slop` | Detect and remove AI-writing tells from markdown prose | +| [`/animation:check-prerequisites`](../plugins/animation/skills/check-prerequisites/SKILL.md) | `animation` | Report whether the tools animation declares resolve. Never installs. | | [`/architecture:record-decision`](../plugins/architecture/skills/record-decision/SKILL.md) | `architecture` | Record an architecture decision in the repository's existing ADR convention | | [`/attribution:audit`](../plugins/attribution/skills/audit/SKILL.md) | `attribution` | Find prose copied from external sources and convert it into pointers | | [`/autonomy:check`](../plugins/autonomy/skills/check/SKILL.md) | `autonomy` | Report whether node and jq resolve for the autonomy hooks. Never installs. | diff --git a/plugins/animation/.claude-plugin/plugin.json b/plugins/animation/.claude-plugin/plugin.json index b644afa983..1b19501e9c 100644 --- a/plugins/animation/.claude-plugin/plugin.json +++ b/plugins/animation/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "animation", - "version": "0.3.2", + "version": "0.4.0", "description": "Hand-drawn-style 2D animation as code, rendered in headless Chromium by an ink brush engine. rotoscope copies a reference clip drawing by drawing: trace to vector paths, render, measure against the source (XOR, SSIM), and fit per-shot brush overrides. learn-style measures a clip into a style pack (ships woodcut-ink) and checks films against it. produce turns a brief into approved boards, a shot list, frames, and a delivered file. setup checks ffmpeg, Node, Chromium, and Python.", "author": { "name": "Melodic Software", diff --git a/plugins/animation/CHANGELOG.md b/plugins/animation/CHANGELOG.md index c9e12bac5b..d1deb0dd72 100644 --- a/plugins/animation/CHANGELOG.md +++ b/plugins/animation/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to the `animation` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.4.0] - 2026-10-03 + +### Added + +- A `SessionStart` hook row reports a missing `node` once per session, on both hook channels, and works on Windows without Git Bash. The notice names `/animation:check-prerequisites`. +- `/animation:check-prerequisites`, a read-only report of whether the tools in `prerequisites.json` resolve, through the shared Node checker. + ## [0.3.2] - 2026-10-03 ### Changed diff --git a/plugins/animation/README.md b/plugins/animation/README.md index 4b7eac8025..84bc8baaa7 100644 --- a/plugins/animation/README.md +++ b/plugins/animation/README.md @@ -8,6 +8,7 @@ Canvas 2D modules (`renderFrame(t)`), headless Chromium draws the frames, and ff | Skill | What it does | |---|---| | `/animation:rotoscope ` | Copies a reference clip drawing by drawing: traces each distinct drawing to vector paths, renders them through the ink.js brush engine, measures every drawing against its source (XOR against a codec-noise floor, SSIM, edge-band SSIM, paper color), fits per-shot brush overrides, and reviews 1:1 crops. Each run appends to a learnings file, and a retro step promotes recurring findings into the defaults. | +| `/animation:check-prerequisites` | Read-only report of whether the tools the plugin declares in `prerequisites.json` resolve; installs nothing. | | `/animation:setup` | Checks the prerequisites (ffmpeg with libx264, ffprobe, Node, playwright-core with Chromium, the pinned numpy and opencv, and the `playwright_core` option when set) and prints a PASS/FAIL/INFO table with one remedy line per failure. Check-only: it installs nothing (the SessionStart hook installs the Python packages). | | `/animation:learn-style ` | Measures a rotoscope work directory into a style pack: palette and tone ramp, the seven style knobs, and statistic bands (edge softness, stroke and gap widths, edge roughness, gray inside the ink, boil of the frame and caption, holds on 1s/2s/3s). Then proves the pack by authoring a new scene with ink.js and checking its render against the bands. | | `/animation:produce ` | From a brief and one or more style packs, writes pre-production boards and stops for approval. After that, a shot list, scenes, rendered frames, a delivered file, and a review against the pack. `shots.json` is the cut list `inkstats.py --cuts` reads. | diff --git a/plugins/animation/hooks/hooks.json b/plugins/animation/hooks/hooks.json index 843b41fd66..dff0143a4e 100644 --- a/plugins/animation/hooks/hooks.json +++ b/plugins/animation/hooks/hooks.json @@ -13,6 +13,12 @@ ], "timeout": 300, "statusMessage": "Installing animation Python packages..." + }, + { + "type": "command", + "command": "sh \"${CLAUDE_PLUGIN_ROOT}/lib/prerequisites.sh\" node-notice /animation:check-prerequisites; ${BASH_VERSION:+exit}; powershell -NoProfile -ExecutionPolicy Bypass -File \"${CLAUDE_PLUGIN_ROOT}/lib/prerequisites.ps1\" node-notice /animation:check-prerequisites", + "timeout": 10, + "statusMessage": "Checking that node is on PATH..." } ] } diff --git a/plugins/animation/skills/check-prerequisites/SKILL.md b/plugins/animation/skills/check-prerequisites/SKILL.md new file mode 100644 index 0000000000..a9213df17f --- /dev/null +++ b/plugins/animation/skills/check-prerequisites/SKILL.md @@ -0,0 +1,38 @@ +--- +description: "Read-only report of whether the external tools the animation plugin declares in prerequisites.json resolve, through the shared Node checker. /animation:setup is the fuller setup report; this skill is the shared checker's. Use when a hook notice says node is missing, or before assuming the animation Python packages were installed. Does not install." +user-invocable: true +disable-model-invocation: false +metadata: + workflow-stage: anytime + summary: Report whether the tools animation declares resolve. Never installs. +--- + +## Purpose + +Run the read-only check. Do not install anything, and do not edit `prerequisites.json`. + +The plugin has no `check` skill, so the prerequisites check has its own name. A hook notice names it. + +## Check + +Run the shared checker through its stub, which reports a missing `node` instead of failing to start: + +```bash +sh "${CLAUDE_PLUGIN_ROOT}/lib/prerequisites.sh" check "${CLAUDE_PLUGIN_ROOT}" --data-dir "${CLAUDE_PLUGIN_DATA}" +``` + +Where there is no `sh` (Windows without Git Bash), run the PowerShell stub with the same arguments instead: + +```powershell +powershell -NoProfile -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/lib/prerequisites.ps1" check "${CLAUDE_PLUGIN_ROOT}" --data-dir "${CLAUDE_PLUGIN_DATA}" +``` + +Report the PASS/FAIL rows as a table. On a FAIL, give the install hints the checker printed. Stop. + +## Next + +A passing check has no successor. For the fuller setup report, run `/animation:setup`. + +## Gotchas + +This skill does not install. A hook notice is not permission to install Node.js. diff --git a/scripts/node-notice-rows.test.sh b/scripts/node-notice-rows.test.sh index c9800d26cc..c791493f76 100755 --- a/scripts/node-notice-rows.test.sh +++ b/scripts/node-notice-rows.test.sh @@ -15,14 +15,12 @@ ROOT="$(cd "$SELF_DIR/.." && pwd)" # shellcheck source=lib/test-harness.sh . "$SELF_DIR/lib/test-harness.sh" -EXEMPT=(animation) # no prerequisites file or check skill yet; the batch that declares it adds both MARKER='prerequisites.sh" node-notice' # --- fleet shape ---------------------------------------------------------------- rows_checked=0 for hooks in "$ROOT"/plugins/*/hooks/hooks.json; do plugin="$(basename "$(dirname "$(dirname "$hooks")")")" - [[ " ${EXEMPT[*]} " == *" $plugin "* ]] && continue mapfile -t rows < <(jq -r '[.hooks.SessionStart[]?.hooks[]? | select((.command // "") | contains("prerequisites.sh")) | .command] | .[]' "$hooks") if ((${#rows[@]} != 1)); then bad "$plugin: want exactly one node-notice SessionStart row" "found ${#rows[@]}" diff --git a/scripts/skill-leaf-name-registry.txt b/scripts/skill-leaf-name-registry.txt index c72e81a02c..496d4c13d1 100644 --- a/scripts/skill-leaf-name-registry.txt +++ b/scripts/skill-leaf-name-registry.txt @@ -154,9 +154,10 @@ check actionlint,autonomy,bash-format,biome-format,harness-ops,context-budget,co # The prerequisites check, for a plugin whose `check` already means something # else (docs/conventions/prerequisites/). instruction-placement gates rule -# globs, skill-quality gates a skill, toolchain builds and tests a project. A -# hook notice names this skill where it would name `check`. -check-prerequisites instruction-placement,skill-quality,toolchain +# globs, skill-quality gates a skill, toolchain builds and tests a project; +# animation has no `check` skill. A hook notice names this skill where it would +# name `check`. +check-prerequisites animation,instruction-placement,skill-quality,toolchain # Fixed verb meaning: mutates the target. disk-hygiene cleans an arbitrary # directory tree, repo-hygiene cleans a repository's caches and git metadata. From 63a16d8662c5f8fa0ff4a2241547fffdfed9575b Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 3 Oct 2026 11:26:57 -0400 Subject: [PATCH 2/3] fix(animation): give check-prerequisites its evals and a one-line Next Co-Authored-By: Claude Opus 5.5 --- .../skills/check-prerequisites/SKILL.md | 4 +- .../check-prerequisites/evals/evals.json | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 plugins/animation/skills/check-prerequisites/evals/evals.json diff --git a/plugins/animation/skills/check-prerequisites/SKILL.md b/plugins/animation/skills/check-prerequisites/SKILL.md index a9213df17f..16f6358b24 100644 --- a/plugins/animation/skills/check-prerequisites/SKILL.md +++ b/plugins/animation/skills/check-prerequisites/SKILL.md @@ -1,5 +1,5 @@ --- -description: "Read-only report of whether the external tools the animation plugin declares in prerequisites.json resolve, through the shared Node checker. /animation:setup is the fuller setup report; this skill is the shared checker's. Use when a hook notice says node is missing, or before assuming the animation Python packages were installed. Does not install." +description: "Read-only report of whether the external tools the animation plugin declares in prerequisites.json resolve, through the shared Node checker. /animation:setup is the fuller setup report; this skill is the shared checker's. Use when: 'animation node notice', 'is animation ready', a hook notice says node is missing, or before assuming the animation Python packages were installed. Does not install." user-invocable: true disable-model-invocation: false metadata: @@ -31,7 +31,7 @@ Report the PASS/FAIL rows as a table. On a FAIL, give the install hints the chec ## Next -A passing check has no successor. For the fuller setup report, run `/animation:setup`. +/animation:setup ## Gotchas diff --git a/plugins/animation/skills/check-prerequisites/evals/evals.json b/plugins/animation/skills/check-prerequisites/evals/evals.json new file mode 100644 index 0000000000..091cf70cd2 --- /dev/null +++ b/plugins/animation/skills/check-prerequisites/evals/evals.json @@ -0,0 +1,41 @@ +{ + "skill_name": "check-prerequisites", + "evals": [ + { + "id": 1, + "name": "node-notice-runs-the-check", + "prompt": "A session-start notice said node is missing for animation. What else is missing?", + "expected_output": "Runs the shared checker through lib/prerequisites.sh check with the plugin root and data dir, then reports each PASS/FAIL row with the install hints it printed.", + "files": [], + "expectations": [ + "Runs `lib/prerequisites.sh check` with the plugin root and --data-dir", + "Reports each FAIL row with the install hint the checker printed", + "Installs nothing" + ] + }, + { + "id": 2, + "name": "install-request-is-declined", + "prompt": "/animation:check-prerequisites\n\nnode is missing. Install it.", + "expected_output": "Reports the rows and the install hints, and does not install Node.js.", + "files": [], + "expectations": [ + "Does not run an installer", + "Prints the install hints the checker produced", + "Does not edit prerequisites.json" + ] + }, + { + "id": 3, + "name": "windows-without-sh-uses-the-powershell-stub", + "prompt": "/animation:check-prerequisites on Windows without Git Bash.", + "expected_output": "Runs lib/prerequisites.ps1 with the same arguments instead of the sh stub.", + "files": [], + "expectations": [ + "Uses `lib/prerequisites.ps1` when there is no `sh`", + "Passes the same check, plugin root and --data-dir arguments", + "Reports the PASS/FAIL rows as a table" + ] + } + ] +} From e2e8ab9327709975e7b7ae711b9501c71f06bc7f Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 3 Oct 2026 11:33:27 -0400 Subject: [PATCH 3/3] fix(animation): point the manifest checks at check-prerequisites and drop the package-verification claim Co-Authored-By: Claude Opus 5.5 --- plugins/animation/CHANGELOG.md | 4 ++++ plugins/animation/prerequisites.json | 12 ++++++------ .../animation/skills/check-prerequisites/SKILL.md | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/animation/CHANGELOG.md b/plugins/animation/CHANGELOG.md index d1deb0dd72..5e9975668f 100644 --- a/plugins/animation/CHANGELOG.md +++ b/plugins/animation/CHANGELOG.md @@ -10,6 +10,10 @@ All notable changes to the `animation` plugin are documented here. Format follow - A `SessionStart` hook row reports a missing `node` once per session, on both hook channels, and works on Windows without Git Bash. The notice names `/animation:check-prerequisites`. - `/animation:check-prerequisites`, a read-only report of whether the tools in `prerequisites.json` resolve, through the shared Node checker. +### Changed + +- Each `prerequisites.json` entry's `check` names `/animation:check-prerequisites`, so a failed row sends the user back to the plugin's own check. + ## [0.3.2] - 2026-10-03 ### Changed diff --git a/plugins/animation/prerequisites.json b/plugins/animation/prerequisites.json index b478ed8630..1983c0d0d6 100644 --- a/plugins/animation/prerequisites.json +++ b/plugins/animation/prerequisites.json @@ -19,7 +19,7 @@ "winget": "OpenJS.NodeJS.LTS", "apt": "nodejs" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" }, { "id": "python3", @@ -48,7 +48,7 @@ "winget": "Python.Python.3.12", "apt": "python3" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" }, { "id": "jq", @@ -69,7 +69,7 @@ "winget": "jqlang.jq", "apt": "jq" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" }, { "id": "ffmpeg", @@ -92,7 +92,7 @@ "winget": "Gyan.FFmpeg", "apt": "ffmpeg" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" }, { "id": "ffprobe", @@ -115,7 +115,7 @@ "winget": "Gyan.FFmpeg", "apt": "ffmpeg" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" }, { "id": "libx264", @@ -143,7 +143,7 @@ "winget": "Gyan.FFmpeg", "apt": "ffmpeg" }, - "check": "/harness-ops:prerequisites" + "check": "/animation:check-prerequisites" } ] } diff --git a/plugins/animation/skills/check-prerequisites/SKILL.md b/plugins/animation/skills/check-prerequisites/SKILL.md index 16f6358b24..83ae8e9c42 100644 --- a/plugins/animation/skills/check-prerequisites/SKILL.md +++ b/plugins/animation/skills/check-prerequisites/SKILL.md @@ -1,5 +1,5 @@ --- -description: "Read-only report of whether the external tools the animation plugin declares in prerequisites.json resolve, through the shared Node checker. /animation:setup is the fuller setup report; this skill is the shared checker's. Use when: 'animation node notice', 'is animation ready', a hook notice says node is missing, or before assuming the animation Python packages were installed. Does not install." +description: "Read-only report of whether the external tools the animation plugin declares in prerequisites.json resolve, through the shared Node checker. /animation:setup is the fuller setup report; this skill is the shared checker's. Use when: 'animation node notice', 'is animation ready', a hook notice says node is missing. It does not verify the hook-installed Python packages; /animation:setup does. Does not install." user-invocable: true disable-model-invocation: false metadata: