fix(card): the eyebrow ran off the canvas, and the check on it counted bytes - #18
Merged
Conversation
…d bytes docs/assets/social-preview.png -- the image every link to this repository renders -- had its eyebrow cut off at the canvas edge. The line is generated from the umbrella's role cell for this pack, 91 characters; at the smallest scale the renderer will use that needs 1354px of a 1200px canvas, so the last 11 characters were never drawn. The card read "...AND THE WALLET UNDER" and stopped. Re-derived here rather than taken on report: decoding the committed PNG puts accent ink at x=1199 of 1200, and replaying the renderer's own metric gives a pen finishing at x=1354 with " LLM RESALE" past the edge. fitScale was already at its floor of 2, so no scale fixes it -- the text itself had to shorten. The role string is now 60 characters: orchestration, prompts, evals, protocols, and the LLM wallet It names all four skills where the old one named three (agent-harness was missing from its own pack's one-line description), and it paints to x=919 -- 196px, 19%, of margin inside the content box. The umbrella owns that cell; this ships the card rendered from it. The sensor gap is the real repair. test/social_preview.py checked the PNG signature, the chunk order, the byte count and the dimensions, and was green over a clipped card for as long as one existed, because none of those readings is about text. test/card_ink.py decodes the image and measures where ink lands: every painted pixel inside the content box, one deliberate exception (the accent bar bleeding to the left edge) which must be PRESENT, so a blank or mis-decoded image cannot pass by having nothing in the gutters. Watched failing before it was believed. The guard refuses the previously committed card by name -- "accent paints at x=1199, y=190 -- 84px past the right edge of the content box ... and reaches the canvas edge, so characters were cut off entirely" -- while the old check printed OK on that same file. A new negative self-test in validate.yml plants one pixel in the last column of a repo copy and requires the entry point to refuse it, with plant_guard.py verify confirming the plant landed. card_ink.py is a separate module on purpose. social_preview.py is shared by nine repositories and the umbrella stops comparing copies below 0.90 similarity -- for all nine at once, the base being this repo's copy. Inlining a PNG decoder there would have disabled that guard on eight repositories that never asked for it. The shared file gains two lines: measured 0.9133. Owed by the umbrella, not by this repo: test/site_test.js byte-compares this card against a render from skills.json, so two edits are needed in the pin commit -- set agent-stack's role to the string above, AND remove agent-stack from LEGACY_FIT in scripts/site.js. The second is not optional: the legacy metric renders the npx line at scale 5, painting to x=1131, which this release's own new check refuses. Verified: with both edits the umbrella generates these exact 8342 bytes; with only the first it does not. B-118, C-01..C-08. Gate: npm test rc=0, plugin validate --strict passed. Co-authored-by: NGHTBOY <NGHTBOY@sshlg.me> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes board row B-118, deferred from v0.17.1 by coordinator decision.
The defect
docs/assets/social-preview.png— the image every link to this repository renders —had its eyebrow cut off at the canvas. The line is generated from the umbrella's
rolecell for this pack, 91 characters; at the smallest scale the renderer will usethat needs 1354px of a 1200px canvas, so the last 11 characters were never
drawn. The card read "…AND THE WALLET UNDER" and stopped.
Re-derived here rather than taken on report:
x 0..1199of 1200fitScalefor the 91-char eyebrowx=1354" LLM RESALE"(11 chars)No scale fixes it. The renderer floors at 2 and was already there, so the text
itself had to get shorter.
The new role string (60 chars)
It names all four skills where the old one named three —
agent-harnesswasmissing from its own pack's one-line description — and paints to
x=919, leaving196px / 19% of margin inside the content box. The eyebrow renders identically
under both fit metrics, so the fix does not depend on which one the umbrella uses.
The sensor gap is the real repair
test/social_preview.pychecked the PNG signature, the chunk order, the byte countand the dimensions — none of which is a reading about text — so it was green over a
clipped card for as long as one existed.
test/card_ink.pydecodes the image and measures where ink actually lands: everypainted pixel must sit inside the content box, with exactly one deliberate exception
(the accent bar bleeding to the left edge), and that bar must be present, so a
blank or mis-decoded image cannot pass by having nothing in the gutters. Clipping
cannot hide from it — losing even one glyph means the line already painted 70px into
the right gutter.
Watched failing before it was believed:
accent paints at x=1199, y=190 — 84px past the right edge of the content box (x=1115), and reaches the canvas edge, so characters were cut off entirely, exit 1OK: … 1200x630, 8686 bytes, exit 0--self-test: clean card accepted, 1px past the box refused, canvas-edge ink refused, blank image refused by the positive assertionvalidate.ymlplant: one pixel in the last column of a repo copy,plant_guard.py verifyconfirms it landed, entry point exits 1Why
card_ink.pyis a separate moduletest/social_preview.pyis a shared mechanism across nine repositories, and theumbrella's divergence check stops comparing copies below
SHARED_SIMILARITY = 0.90—for all nine at once, the base being this repository's copy. Inlining a PNG decoder
there would have silently disabled that guard on eight repositories that never asked
for it. The shared file gains two lines; measured similarity to its eight siblings is
0.9133. Its docstring says this so the next reader does not merge it back.
Owed by the umbrella, not by this repository
test/site_test.jsbyte-compares this card against a render fromskills.json, sothe umbrella is red until two edits land in the pin commit:
roleto the 60-char string above, verbatim;agent-stackfromLEGACY_FITinscripts/site.js.The second is not optional. The legacy metric renders
npx skills add ssheleg/agent-stackat scale 5, painting to
x=1131— 16px past the content box — which this release's ownnew check refuses. The umbrella's own comment already names B-118 as the moment that
entry retires, and the two remaining entries still need the gate, so the exactness
fixture stays green.
Verified against the umbrella working copy: with both edits
memberCardSpec+og.cardproduce these exact 8342 bytes; with only the first, they do not.Gate
Run on an isolated
git worktreeof this branch (a sibling agent holdsB-126-kv-cachein the shared tree, so its in-flight edits are excluded and not staged here):
npm test→ exit 0 —OK: agent-stack structurally valid (13 checks = 9 named + 4 per-skill, 4 skill(s), v0.18.2),PASS: plant_guard — 9 cases,PASS: installer — 11 case(s), every residue lineleft nothingpython3 test/social_preview.py→OK: docs/assets/social-preview.png is 1200x630, 8342 bytespython3 test/card_ink.py --self-test→ exit 0python3 test/evals_validate.py+--self-test→ exit 0claude plugin validate . --strictandplugins/agent-stack --strict→✔ Validation passedpackage.json,.claude-plugin/marketplace.json,plugins/agent-stack/.claude-plugin/plugin.json