feat: use the product's own mark for the app icon and sidebar - #103
Conversation
7d0cccd to
e57b570
Compare
|
Rebased onto Two conflicts, and the interesting one was not textual.
Resolved by removing the generation task and keeping the Everything else auto-merged correctly, and I checked rather than assumed:
Re-verified after the rebase: all six icon sizes plus |
9c4f066 to
2c8096c
Compare
The sidebar rendered lucide's generic <Boxes> glyph -- a stock icon standing in
for a brand that did not exist yet -- and build/appicon.png was a hard-edged
opaque square with white in all four corners. macOS does not round app icons,
so that square is what shipped.
The mark is traced from the master raster in the site repository rather than
redrawn, so the geometry stays the designer's. It paints fill="currentColor"
instead of the brand's #007AFF: that value equals --blue on the light theme
exactly, but the dark theme sets --blue to #0a84ff, so a literal would be
visibly off against every other blue in the window.
Windows was carrying the default executable icon. The previous icon task passed
-windowsfilename "" and no .ico existed at all, so this adds one, plus the
manifest and version info a .syso needs. The 16x16 entry is hand-drawn: scaling
the full mark down puts the ring stroke, its counter, and the inner form each
under 2.4px, which blends them into a solid block and loses the break in the
ring. That size is what Explorer and the taskbar use.
The syso step is repeated in build-artifacts.yml because that workflow calls
`go build` directly instead of going through the Taskfile. Doing it in only one
place would leave every released .exe on the default icon while local builds
looked correct.
Linux needs no icon: the release matrix builds macOS and Windows only.
Two things found while wiring this up:
- `.brand-lockup span:last-child` was meant for the tagline but matched any
last-child span in the lockup, including the one now wrapping the mark, and
painted it --text-secondary. It stayed hidden only while the mark was an
<svg> rather than a <span>.
- NOTICE described the icon inventory as vendor marks from lobe-icons plus the
OpenClaw derivative. A first-party mark must not be read as covered by that,
and the licence generator only diffs third_party/ -- it does not check this
prose.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test_every_shipped_image_asset_is_registered walked the assets directory and required every image to appear in asset-rights.json. That gate is right about the thing it was built for -- an unregistered third-party file ships with no source, licence or hash, and --check still passes -- but it assumed everything in that directory is third-party, which the product's own mark is not. Satisfying it by adding the mark to `assets` would have been the wrong fix: that entry means "here is the vendor, licence text, owner and hash", and our own artwork has none of those to give. It is covered by the repository's own licence, so a lobehub-shaped entry would assert a provenance that does not exist. So the manifest now has a separate `firstPartyAssets` group, and the gate accepts a file recorded in either. What it still refuses is a file in neither, which is the actual failure it was written to catch. A second test keeps the two groups from blurring: a first-party entry may not carry source, license, licenseSource, copyrightOwner or sha256, and no file may appear in both. collect_asset_dependencies reads only `assets`, so the new group cannot leak into THIRD_PARTY_NOTICES.md as a dependency. docs/distribution-compliance-policy.md needs no change -- it already lists "OneAgent's own icons" as distributable and scopes the inventory requirement to third-party files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2c8096c to
7b38736
Compare
|
Rebased again onto We had independently solved the same problem — both branches added
Kept from this branch: the tracked One change I did make to their code. Both the Taskfile and the workflow regenerated Two things the automatic merge got wrong that were worth catching by hand:
Re-verified after the rebase: the hand-drawn 16×16 (318 bytes) plus |
Closes #98.
Replaces the placeholder mark and the old app icon with the product's own logo, across every surface that had one.
What was wrong
<Boxes>glyph — a stock icon from the icon library standing in for a brand that did not exist yet.build/appicon.pngmeasured 1024×1024, 100% opaque, white in all four corners. macOS does not round app icons for you; the artwork has to carry its own squircle, so that square is what shipped.-windowsfilename ""and no.icoexisted anywhere in the repo, so released.exefiles carried the default executable icon.Approach
The mark is traced from the master raster in the site repo (
public/images/brand/oneagent-logo.png) rather than redrawn, so the geometry stays the designer's. Verified by rasterising the traced path back and comparing coverage against the source: 33.7% both ways, with the ring, the inner form, and the break at the lower right all intact.The app icon is rebuilt at 1024 from the bare mark rather than upscaled from the site's 512 plated PNG, using geometry measured off that asset: full-bleed plate, corner radius 20.5% of the edge, superellipse exponent ~1.75, mark at 71.3% centred. Result matches the reference at 4.3% transparent versus 4.4%.
It paints
fill="currentColor"instead of the brand's#007AFF. That value equals--blueon the light theme exactly, but the dark theme sets--blueto#0a84ff, so a literal would be visibly off against every other blue in the window. Confirmed in the browser:#007affon light,#0a84ffon dark.The 16×16 problem
Scaling the mark down puts every feature under the pixel budget:
At 16px the ring, the gap, and the inner form each land on roughly two pixels and blend into a solid block — the break in the ring disappears entirely. I confirmed this by extracting the entry
wails3 generate iconsproduces and inspecting it.Since 16×16 is what Explorer and the taskbar use, that entry is hand-drawn: the ring alone at a weight that survives, keeping the silhouette recognisable rather than preserving detail that cannot render. The other five sizes are scaled normally.
build/Taskfile.ymlcarries a comment explaining that regenerating the.icowholesale discards it.Two things found while wiring this up
A CSS selector that was already too broad.
.brand-lockup span:last-childwas meant for the tagline but matched any last-child span in the lockup — including the one now wrapping the mark — and painted it--text-secondary. It stayed hidden only while the mark was a Lucide<svg>rather than a<span>. Fixed the selector rather than piling specificity on the new rule.The workflow does not use the Taskfile.
build-artifacts.ymlcallsgo builddirectly, so adding the.sysostep only tobuild/windows/Taskfile.ymlwould have left every released.exeon the default icon while local builds looked correct. The step is in both places, with a comment saying why.Compliance
The mark is first-party, so it deliberately does not go in
asset-rights.json— that file tracks vendor artwork with a recorded source, licence, and SHA-256, and registering ours there would assert a third-party provenance it does not have. A test asserts it stays out.NOTICEdescribed the icon inventory as vendor marks from lobe-icons plus the OpenClaw derivative. Added a paragraph so a first-party mark is not read as covered by that. Worth flagging: the licence generator only diffsthird_party/and does not check this prose, so nothing would have caught the drift.Not done, deliberately
No Linux icon. The release matrix in
build-artifacts.ymlbuilds macOS and Windows only, so a Linux icon would be an unused file.The SVG is a traced polyline (320 points, 3.8KB) rather than curve-fitted. Faithful and verified, and small next to the 46KB CSS bundle, but a hand-authored vector from the designer would be smaller. Worth asking for if one exists.
Verification
Windows resources confirmed embedded in a cross-compiled
.exe— all six icon sizes present by byte signature, plusProductName,CompanyName, anddpiAwareness. Sidebar mark verified in the browser in both themes.🤖 Generated with Claude Code