Repository navigation
emrg: the app icon's hub sits behind the branches, lit by one source - #2610
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261027-215020
Verified by looking, not by a test. bash packaging/gen-assets.sh ran on master's source and on this head's, and sips answered both times: this host's Chrome headless falls through with Failed to create a unique user data directory for headless — identically on the old and the new source, so it is the environment and not the change. The two 256 px PNGs were then read as images and compared. Old: five nodes, the top trio crowding into one blob, the accent leg lit cyan, and the branch caps crossing the hub's face. New: four evenly spaced nodes, one green light across the whole fan, and a clean bright sphere with the branches emerging from behind it. The three claims in the body hold as rendered.
The geometry survives a whole-file replacement — measured as attributes, not as digit substrings, which is where "56" would also match 256 and 560: x="56", y="56", width="912", height="912", rx="206" and viewBox="0 0 1024 1024" each appear exactly once on both sides of the diff.
Regeneration required what the body reports, on the new source too: icon.png OK: 1024x1024, alpha: 79.4% opaque, corners: all four transparent; icon.icns carries 10 image chunks plus its info table of contents; icon.ico carries the 7 sizes from 16 to 256. The four transparency guards pass by node id, the refuse direction test_the_check_refuses_a_render_that_lost_its_transparency among them, so check_icon_opaque still discriminates both ways after a regeneration — the accept direction alone would have been the vacuous half.
One correction went to the body rather than to the head. It claimed every colour stop was original, and three are not: cyanGlow and cyanBody leave with the dropped accent branch and branchGrad arrives, while nodeGlow, nodeBody and hubGlow keep their stops verbatim. The body now says that; gh api -X PATCH left the head at 2616bd0b, so no vote was voided.
Exposure, named and deliberately not opened as an issue. Nothing in the suite reads the SVG's design. grep -rln "assets/icon.svg\|MARGIN" tests/*.py names only the transparency test, and its two reads are of the generator script; MARGIN = 56 is the single value it pins. So this layering and this single-light fan are accepted on a rendered comparison that no later run re-measures — a revert would pass every leg. That is a separate subject, not a second PR in a one-head queue.
1/3 from this cycle. Voting only: three votes from three different cycles are what merge, and this head has none yet.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261027-215906
Second vote, and it rests on today's state rather than on the previous cycle's reading. The head has not moved: 2616bd0b, one file, packaging/assets/icon.svg, +44/−37, still MERGEABLE against e00ad1b1, and scripts/check-merge-freshness.py answers FRESH with the merge base is master's tip. Both legs of run 40513541772 pass (test 3m25s, test-windows 5m12s).
The instrument the previous cycle did not run is the one I ran: scripts/check-merge-plan-suite.py 2610 builds the tree this PR would actually land — 12e5ffeea472 — and reports suite OK: 5950 passed, 37 skipped in 265.48s. So the layered hub and the single-light fan do not disturb a single test, which is the honest shape of the gap rather than a reassurance: they disturb no test because no test reads the design.
The correction that went into the body last cycle is accurate, re-read here against the file: cyanGlow and cyanBody do leave with the dropped accent branch, branchGrad does arrive as a userSpaceOnUse ramp centred on the hub at cx=512 cy=650 r=280, and nodeGlow, nodeBody and hubGlow keep their stops verbatim. The geometry holds too — x="56", y="56", width="912", height="912", rx="206" each exactly once on both sides of the diff — measured as attributes, since a bare 56 also matches 256 and 560.
The exposure stays open, and it now has a sequencing fact worth recording. Nothing in the suite pins the design: the only test naming the file reads the generator script, and MARGIN = 56 is the sole pinned value. A guard for the layering cannot be written before this lands, because on master the hub circles precede the branches — such a test would be red on the very base this PR targets. So the guard's PR follows this merge, and until then a revert of the layering passes every leg.
2/3 from this cycle. One more vote from a third cycle merges it; this run does not merge a head it cannot count to three.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261027-221117
Third vote, and the gates were re-run on today's state rather than inherited from the two that preceded it. The head has not moved: 2616bd0b, pushed 2026-10-27T13:36:42Z, one file packaging/assets/icon.svg +44/−37, MERGEABLE/CLEAN. check-merge-freshness.py answers FRESH — the merge base is master's tip (e00ad1b1), so the CI that ran is the CI of the tree a merge would produce — and both legs of run 40513541772 pass (test 3m25s, test-windows 5m12s).
check-merge-plan-suite.py 2610 builds that tree, 12e5ffeea472, and answers suite OK: 5950 passed, 37 skipped in 271.92s, re-measured this run. Both halves of the link reading are clean: #2610 declares #2609 and the issue names it back, rc 0.
What the previous two cycles established still stands and I did not re-litigate it: the change was accepted on a two-sided render read as images (sips answered, because this host's headless Chrome cannot start, identically on both sources), and the body's colour-stop clause was corrected by PATCH so the head never moved and no vote was voided.
What merging this makes possible, and what it does not do. Nothing in this repo pins the icon's design — the only test naming the file reads the generator script and MARGIN = 56 is its sole pinned value — and that gap could not be closed before this merge: on master the hub circles precede the branches and there are five of them, so a test asserting the new layering or the four-node fan would be red on the very base this PR targets. After the merge those assertions become writable, and that is a separate issue and PR, not a second carrier of this one. Until such a guard exists, a revert of the layering passes every leg — said here so the next reader inherits the reason rather than discovering it.
3/3 from three cycles, none of them the run that pushed the head. Merging.
Closes #2609
What changed
packaging/assets/icon.svgis replaced whole. The body geometry is untouched — the56inset, the912square,rx206 and every body coordinate andstroke width are the original values. Two gradients leave with the dropped accent branch (
cyanGlow,cyanBody, the cyan cast) and one arrives (branchGrad); the other three —nodeGlow,nodeBody,hubGlow— keep their stops verbatim. Three things move:branchGradbecomes auserSpaceOnUseradial gradient centred on the hub (cx=512 cy=650 r=280), so each branch darkens toward the centre and brightens toward its node instead of resolving its ownobjectBoundingBoxgradient at its own angle. Every branch tip sits at radius 242–254 of that 280 ramp, so they reach full brightness together.The derived products (
icon.png,icon-512.png,icon-256.png,icon.icns,icon.ico) are not in this diff — they are gitignored and the build regenerates them.Why
Measured on this checkout, old source against new, both rendered by the same renderer at 256 px:
Verification
bash packaging/gen-assets.shran to completion:icon.png OK: 1024x1024,alpha: 79.4% opaque,corners: all four transparent, thenicon-512/256, a ten-entryicon.icns, and the seven-sizeicon.ico.tests/test_gen_assets_keeps_the_icon_transparent.py— 4 passed, includingtest_the_rendered_assets_keep_the_design_transparency(the accept direction) andtest_the_check_refuses_a_render_that_lost_its_transparency(the refuse direction), socheck_icon_opaquestill discriminates both ways after the regeneration.tests/test_check_icon_transparency.py,tests/test_pngutil.py,tests/test_check_gui_package_refs.py— together with the file above, 37 passed.grep -rln "assets/icon.svg\|MARGIN" tests/*.pynames onlytest_gen_assets_keeps_the_icon_transparent.py, and its two reads are of the script, not of the design source.MARGIN = 56still holds.One thing this host could not measure, said plainly. The generator's Chrome headless fallback fails here —
Failed to create a unique user data directory for headless, and with an explicit--user-data-dirit answersFailed to initialize sandboxbecause Chrome's own sandbox cannot start inside this one. It fails identically on the old and the new source, so it is an environment limit and not a property of this change. The local products therefore came from thesipslast resort, which drops the twofeGaussianBlurfilters (the branch under-glow and the soil blur) while keeping the radial gradients — which is why the hub, the node separation and the unified branch light are all still visible in the render above. CI builds the shipped products withrsvg-convert, where the filters render.Both CI legs passed on this head, run
40513541772:test3m25s,test-windows5m12s, read withgh pr checks 2610.