Skip to content

Releases: cportka/claude-plugins

portka-tools 1.8.0

Choose a tag to compare

@cportka cportka released this 10 Jul 18:21
c48042a

Triage of #85video-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-time splits the clip into N windows (--segments, default 8) and prints
    each window's palette as t<sec> #hex #hex …, so the colour journey is visible. Reuses
    palettegen per 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 a loopcheck.png strip (first │ last) so the seam is visible. Built on the
    PPM reader + the --strip hstack. 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 -y fix
    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 and win.ppm is 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, not format=duration.
  • A 10-bit/HDR source (ffmpeg emits a 16-bit rgb48be PPM) 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; --segments is
    capped at 200; and every ffmpeg write uses -y -nostdin.

Tests

  • New coverage: --palette --over-time prints a per-window arc whose windows genuinely differ (a
    regression guard for the stale-frame bug); --loop-check calls 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-time without --palette exits 2; and both dry-runs
    print their commands. Suite: 217 passed, 0 failed, 1 skipped.

portka-tools 1.6.0

Choose a tag to compare

@cportka cportka released this 08 Jul 04:29
c01082e

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 ready gh issue create … --label feedback command) and to treat
    a co-located marketplace repo as read-only — never open a branch/commit/PR on it. gh issue is
    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 run gh 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 forbids main: skip the main checkout, 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, and test_version_sync.py matched 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 test is wired up for manifest repos. A package.json with no test script (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 the node --test tests/ form that throws ERR_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-standard CI ships no language toolchain (no setup-node/npm ci), so a repo
    whose tests/cases/*.sh call a real toolchain is red on the runner though green locally (#81).
  • A bare VERSION plus a later-added manifest can silently drift (the runner binds to the
    top-priority source only); an optional --pages deploy 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.test is wired for a script-less package.json; the managed CLAUDE.md carries the
    feedback-funnel, manual-release, and branch-pinned guidance; gh issue is 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 fake ffprobe injects the rates). Suite: 210 passed, 0 failed, 1 skipped.

portka-tools 1.5.0

Choose a tag to compare

@cportka cportka released this 06 Jul 22:12
8ff42c8

Triage of the DedTxt dogfood feedback #79app-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 --url mode needs curl to 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 -sSI output) to still score the live HSTS / CSP / X-Content-Type-Options
    / Referrer-Policy
    header checks. Exactly one of --url / --dir / --html; --headers requires
    --html; --html - and --headers - can't both read stdin.
  • Source-visible Security sub-score — Security is no longer a blanket n/a off 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 / --html now score these — a <meta> CSP and a shipped
    security.txt are 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 reads n/a — honest.
  • --dir source-tree foot-gun guard. Many sites generate robots.txt / sitemap.xml /
    .well-known/security.txt at build time, so pointing --dir at src/ false-negatives Crawlability
    and Security. When --dir looks like a source tree (a package.json build script, or a src/
    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.md and reference.md document 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: --html scores a pre-fetched page (file and stdin) with no origin fetch; --headers
    drives the security-header checks in --html mode; the argument guards (--headers without
    --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-origin srcs are
    ignored; and a source-tree --dir warns to point at the build. The existing dir-mode star / #63
    coverage tests still hold (a control-free page keeps Security n/a).

portka-tools 1.4.1

Choose a tag to compare

@cportka cportka released this 05 Jul 19:43
6d24472

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/--stutter no longer lets a recording's pre-roll dominate "choppiest windows". A
    clip that starts on a black screen / URL bar / static splash reads (after mpdecimate) as a run of
    0 fps windows, 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 own compile/prime timing 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 existing t,unique_frames,fps stdout).

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.