Skip to content

Commit bcb9209

Browse files
jeffmerrickclaude
andauthored
Blog feature image lint: require an approved PNG Software tag (#21094)
* Blog feature images: reject an untagged PNG in lint The Software-tag allowlist in checkFeatureImageSoftware accepted "Figma", our renderer's stamp, or *no tag at all* — the last one covering legacy skill output from before compose_meta_image.py started stamping. That allowance was the widest hole in the four feature-image checks: an absent Software tag is the default output of every ad-hoc image writer (Pillow, canvas, sips, ImageMagick, a headless-browser screenshot), so an agent that hand-rolls a 1884x1256 image on a #231F33 backdrop passes the dimension, background, and C2PA checks and then sails through this one too. Verified against a hand-authored title card: it linted clean. Drop the allowance and back-stamp the 36 pre-stamp renders instead, so the tag is required rather than grandfathered. The stamp is inserted as a tEXt chunk after IHDR with no re-encode — every one of the 36 decodes pixel-identical to what it replaced, and all 811 blog meta cards still render (satori/resvg reads them unchanged). Also note the consequence for designers in the skill: a supplied image that isn't a straight Figma export (re-saved elsewhere, or optimized with metadata stripped) now fails lint, and the fix is to ask for the original export — never to write a tag onto the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Tag the one back-stamped designer image as Figma pulumi-do-direct-resource-operations/feature.png is a designer image, not a template render, so the renderer's stamp claimed something the file can't back. It went out with the rest of the batch because it carried no Figma tag to keep. Comparing every back-stamped image against the templates outside their catalog.yaml placeholder boxes puts 35 of the 36 on a template at 0.0000; this is the only one that isn't. Retag it Figma so the two allowed values keep meaning what they say. Pixels are untouched — the file still decodes identical to master. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent dd86ad3 commit bcb9209

39 files changed

Lines changed: 19 additions & 10 deletions

File tree

.claude/commands/blog-feature-image/SKILL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ If **I have a designer-supplied image** is selected:
8282
```
8383
3. Skip straight to Step 4.
8484

85+
> **`make lint` only accepts two PNG `Software` tags**: `Figma` (a designer's Figma export) and `pulumi-blog-feature-image` (this skill's renderer). An **untagged** PNG now fails, because that's what every ad-hoc image writer produces by default. So a designer-supplied file that isn't a straight Figma export — re-saved from another tool, or run through an optimizer that strips metadata — will fail lint even though it's legitimate. **Do not "fix" that by writing a tag onto the file.** Report the failure to the user and ask them for the original Figma export.
86+
8587
---
8688

8789
### Question 2: Feature template

.claude/commands/blog-feature-image/scripts/compose_meta_image.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,10 @@ def compose(config: dict, output_path: str, assets_dir: Path) -> str:
308308
final.paste(canvas, (0, 0), canvas if canvas.mode == "RGBA" else None)
309309

310310
# Stamp a PNG Software tag so the render is positively identifiable as our
311-
# pipeline's output (rather than relying on absence of metadata). The lint
312-
# allowlist in scripts/lint/lint-markdown.js must accept this exact string —
313-
# keep FEATURE_IMAGE_SOFTWARE there in sync if this value changes.
311+
# pipeline's output. The lint allowlist in scripts/lint/lint-markdown.js
312+
# accepts only this string and "Figma" — an untagged PNG is a lint failure,
313+
# so dropping this stamp would fail every image this script renders. Keep
314+
# FEATURE_IMAGE_SOFTWARE there in sync if this value changes.
314315
meta = PngImagePlugin.PngInfo()
315316
meta.add_text("Software", "pulumi-blog-feature-image")
316317
final.save(str(output), "PNG", pnginfo=meta)
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading
46 Bytes
Loading

0 commit comments

Comments
 (0)