Releases: cportka/claude-plugins
Release list
portka-tools 1.8.0
Triage of #85 — video-bug-analyzer as an art/aesthetic-reference tool (mining a library of animated
GIF loops for palette + motion). video-bug-analyzer → 1.8.0 (repo-bootstrap and
app-website-evaluator stay 1.7.0, tab-chord-formatter 1.2.0). MINOR: two new analysis modes, both
built on existing plumbing, plus a framing tweak.
Added (video-bug-analyzer → 1.8.0, #85)
--palette --over-time— the colour arc, not one flattened ramp. A seamless art loop often
sweeps through very different colour states (powder-blue → magenta/cyan → back); a single dominant
palette hides that.--over-timesplits the clip into N windows (--segments, default 8) and prints
each window's palette ast<sec> #hex #hex …, so the colour journey is visible. Reuses
palettegenper window + the existing PPM swatch reader; honors--colors,--start/--end.--loop-check— is this a clean seamless loop? Reports the mean absolute pixel difference
between the first and last frame (0 = identical wrap; <1% "loops cleanly", <4% near-seamless, else a
visible seam) and writes aloopcheck.pngstrip (first │ last) so the seam is visible. Built on the
PPM reader + the--striphstack. Broadly useful to anyone making loops, GIFs, or shader toys.- "Also useful for" framing (#85 item 5, echoing #14). The header/README/marketplace now call out
the non-bug uses — art/colour reference, asset/QA — and that GIF input works on every mode, so
the tool surfaces for an aesthetic-reference task, not just "bug/glitch/crash".
Deferred to IMPROVEMENTS.md
--montage a.gif,b.gif,…— an N-way library survey (one representative tile per input), for
eyeballing a whole collection at once (distinct from the pairwise--compare-videos).--palette(and--over-time) as an SVG/PNG swatch sheet artifact, not just hex text.
Pre-merge adversarial review hardening
A multi-agent review of the new ffmpeg/python code caught several real edge cases, all fixed:
- A window that decodes zero video frames no longer fabricates a stale palette (the
-yfix
wasn't enough — ffmpeg's image muxer opens lazily, so the prior window's file survived): the span
is clamped to the video stream duration andwin.ppmis removed before each window. - A clip whose audio outlasts its video no longer sends
--loop-check's tail seek into an
audio-only region (a false "could not extract" error): both modes use the video stream
duration, notformat=duration. - A 10-bit/HDR source (ffmpeg emits a 16-bit
rgb48bePPM) is read correctly —-pix_fmt rgb24
on frame grabs plus a parser that takes the high byte of each 16-bit sample — instead of garbage
hex / a diff that ignores half the frame. - A first/last frame size mismatch (a mid-clip resize) is reported as such rather than diffing
misaligned pixels; a truncated/malformed PPM header no longer crashes the parser;--segmentsis
capped at 200; and every ffmpeg write uses-y -nostdin.
Tests
- New coverage:
--palette --over-timeprints a per-window arc whose windows genuinely differ (a
regression guard for the stale-frame bug);--loop-checkcalls a static clip a clean loop (+ writes
the strip) and a hue-sweeping clip a seam; a clip whose audio outlasts its video survives both
modes (no stale rows, no false error);--over-timewithout--paletteexits 2; and both dry-runs
print their commands. Suite: 217 passed, 0 failed, 1 skipped.
portka-tools 1.6.0
Triage round: repo-bootstrap #81 + a mis-filed field report, and video-bug-analyzer #83.
repo-bootstrap → 1.6.0 and video-bug-analyzer → 1.6.0 (app-website-evaluator stays 1.4.0,
tab-chord-formatter stays 1.2.0). MINOR overall: new Portka-standard guidance + backward-compatible
scaffold correctness fixes and a heuristic refinement.
Portka standard — funnel feedback, leave releases to humans, respect branch-pinned sessions
The workflow CLAUDE.md that repo-bootstrap --portka-standard installs (and this repo's own copy)
gained three standing rules, prompted by a field report that arrived as a branch on this repo
instead of an issue — the funnel this fixes:
- Feedback goes to the marketplace's issue tracker, not stray branches. A new "Reporting feedback
on the tools you use" section tells an agent to file a Plugin feedback issue on
cportka/claude-plugins(with a readygh issue create … --label feedbackcommand) and to treat
a co-located marketplace repo as read-only — never open a branch/commit/PR on it.gh issueis
added to the permissions allowlist so the command is pre-approved. - Releasing is the user's manual step. Prepare the release in the PR (version + CHANGELOG), but
never create/push a git tag or rungh release— hosted/sandbox environments block tag pushes, so
it just fails. The user tags and cuts the release from the GitHub web UI after merge. - Branch-pinned sessions. Step 1 now acknowledges hosted runs (e.g. Claude Code on the web) where
the harness pins work to a feature branch and forbidsmain: skip themaincheckout, open the PR
from the assigned branch, and let a human merge — resolving the update-main-first vs. never-touch-main
tension the field report hit.
Fixed (repo-bootstrap → 1.6.0, #81 + field report)
- Scaffolded CHANGELOG check is now anchored to a real release heading. The generated
tests/run-tests.sh,version-sync.test.mjs, andtest_version_sync.pymatched the version as a
bare substring — so a URL, a prose mention, or an unrelated version satisfied it and a CHANGELOG
with no## [x.y.z]section for the current version could ship green. All three now require a
## [version]heading (dots escaped, brackets optional). npm testis wired up for manifest repos. Apackage.jsonwith notestscript (the common
case the #59 native binding targets) now gets"test": "node --test"merged in (never clobbering an
existing one), so the repo's own command runs the sync test — and the "run with" hint uses bare
node --test, never thenode --test tests/form that throwsERR_MODULE_NOT_FOUND.
Fixed (video-bug-analyzer → 1.6.0, #83)
- The
smoothness:banner no longer cries "choppy" on a high-refresh capture. A 120 Hz ProMotion
recording of a 60 fps app reads as ~57 effective fps vs 120 nominal — which the heuristic reported
as "~52% frames dropped/duplicated — likely choppy," a false positive (the duplicated frames are
expected when the display refreshes faster than the app renders, not jank). When the nominal rate is
a high display refresh (≥ 90 Hz) and the effective rate lands near a common animation cadence
(~30/~60 fps), the banner now says e.g. "~57 fps content on a 120 Hz capture — normal for a 60 fps
app, not choppy; --motion/--pacing to check for real stutter." Irregular shortfalls (effective not
near a common cadence) are still flagged, and normal-refresh captures are unchanged.
Deferred to IMPROVEMENTS.md
- Greenfield
--portka-standardCI ships no language toolchain (nosetup-node/npm ci), so a repo
whosetests/cases/*.shcall a real toolchain is red on the runner though green locally (#81). - A bare
VERSIONplus a later-added manifest can silently drift (the runner binds to the
top-priority source only); an optional--pagesdeploy scaffold for greenfield front-ends; and an
end-of-run "wrote N files" summary.
Tests
- New coverage: the scaffolded CHANGELOG check rejects a loose-only version mention (bash + node:test);
scripts.testis wired for a script-lesspackage.json; the managedCLAUDE.mdcarries the
feedback-funnel, manual-release, and branch-pinned guidance;gh issueis in the allowlist; and the
smoothness:banner treats a 60 fps app on a 120 Hz capture as normal while still flagging a real
shortfall (a fakeffprobeinjects the rates). Suite: 210 passed, 0 failed, 1 skipped.
portka-tools 1.5.0
Triage of the DedTxt dogfood feedback #79 — app-website-evaluator's first real --dir run on a
shipping static site (DedTxt scored A* 100/100 over 82% of weight). app-website-evaluator →
1.4.0 (video-bug-analyzer stays 1.4.1; repo-bootstrap and tab-chord-formatter unchanged at
1.2.0). MINOR: a new pre-fetched input mode + a source-visible Security sub-score, both
backward-compatible.
Added (app-website-evaluator → 1.4.0, #79)
--html <file|-> [--headers <file|->]— score already-fetched HTML without curl reaching the
origin. The primary--urlmode needscurlto hit the origin, but web/remote Claude Code runs
behind an egress proxy that 403s arbitrary hosts (DedTxt was blocked outright), so the whole live
path was unavailable. Now an agent that fetched the page another way — an MCP tool, a headless
browser,web_fetch— can pipe it in (… | evaluate-site.sh --html -) or pass a file, and pair
--headers(e.g.curl -sSIoutput) to still score the live HSTS / CSP / X-Content-Type-Options
/ Referrer-Policy header checks. Exactly one of--url/--dir/--html;--headersrequires
--html;--html -and--headers -can't both read stdin.- Source-visible Security sub-score — Security is no longer a blanket
n/aoff the network (18% of
weight). A static host can't set HTTP headers, but it ships controls that are visible in the
build: a<meta http-equiv="Content-Security-Policy">, a/.well-known/security.txt, and its
third-party<script>posture.--dir/--htmlnow score these — a<meta>CSP and a shipped
security.txtare credited, and zero third-party<script>origins (all scripts same-origin /
relative) is scored as the real minimal-supply-chain-surface win it is; third-party origins are
listed with a "pin with SRI" nudge. Header CSP still wins when present (the<meta>check stands
down to avoid double-counting). A truly control-free static page still readsn/a— honest. --dirsource-tree foot-gun guard. Many sites generaterobots.txt/sitemap.xml/
.well-known/security.txtat build time, so pointing--diratsrc/false-negatives Crawlability
and Security. When--dirlooks like a source tree (apackage.jsonbuild script, or asrc/
with no root robots.txt/sitemap.xml), the tool now prints a NOTE to target the built/deployed output
(dist/,build/,out/).- The scorecard's partial-coverage footnote now says source-visible Security is scored and only the
live signals (HTTPS / response headers, real perf numbers) need the origin — via--url,
--html --headers, or Lighthouse.
Docs
SKILL.mdandreference.mddocument the three input sources, call out the build-vs-source
gotcha explicitly (generated robots/sitemap/security.txt), and explain the source-visible Security
signals; README gains a--html/proxy example and the plugin-table copy is refreshed.
Tests
- New coverage:
--htmlscores a pre-fetched page (file and stdin) with no origin fetch;--headers
drives the security-header checks in--htmlmode; the argument guards (--headerswithout
--html, both-stdin) exit 2; a<meta>-CSP +security.txt+ no-third-party-scripts build makes
Security a scored dimension; third-party<script>origins are flagged while same-originsrcs are
ignored; and a source-tree--dirwarns to point at the build. The existing dir-mode star / #63
coverage tests still hold (a control-free page keeps Securityn/a).
portka-tools 1.4.1
Triage of round-6 dogfood feedback #70. video-bug-analyzer → 1.4.1 (others unchanged). PATCH: a
correctness refinement to --cadence, backward-compatible.
Fixed (video-bug-analyzer → 1.4.1, #70)
--cadence/--stutterno longer lets a recording's pre-roll dominate "choppiest windows". A
clip that starts on a black screen / URL bar / static splash reads (aftermpdecimate) as a run of
0 fpswindows, which previously topped the choppiest-windows ranking and competed with the
freeze-gap section — pointing a reader at the pre-roll seconds instead of the real stutter. On an
unscoped scan the tool now detects that leading static/near-black lead-in, excludes it from the
ranking, and notes where content starts (a frozen splash in the lead-in still surfaces in the
freeze gaps, which correctly caught it). The freeze-gap pass — which the reporter confirmed mapped
1:1 onto the app's owncompile/primetiming marks — is unchanged. Scoped scans
(--start/--end) are unaffected; a continuous clip still gets the generic scoping hint (#64).- The reporter's low-priority "machine-readable freeze-gap CSV" ask is recorded in
IMPROVEMENTS.md (it needs an output-shape decision so a second table doesn't
confuse consumers of the existingt,unique_frames,fpsstdout).
Pre-merge adversarial review hardening: the lead-in is only treated as pre-roll when it is genuinely
near-static (idle windows and a busiest window far quieter than the content) — so active content
that merely freezes early (active → 0 fps → active) is not mistaken for pre-roll and its frozen
windows stay in the ranking, which is exactly what --cadence must headline.
Tests
- New coverage: a 3s-black-pre-roll + 2s-content clip confirms the dead lead-in is excluded from the
choppiest windows, the content-start note fires, and the freeze-gap pass still reports the frozen
splash; an active-then-early-freeze clip confirms the frozen windows are kept in the ranking
(not misread as pre-roll) — while the continuous-clip #64 scoping behavior is preserved.