SPB Git

spb/zyquo-mlx Public MIT

The local MLX foundry for your Mac — run, fine-tune, quantize, and ship models. Nothing leaves your machine.

Swift 93.4% Python 3.8% Makefile 2.2% Shell 0.5%

phase5: legendary foundry icon — Z-anvil/spark direction, SVG source of truth, small-size variant, make icon pipeline, Dock-verified

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 11 days ago (Jul 30, 2026) parent eeb56d6

Showing 7 changed files with +315 and −1

modified .gitignore +1 −0
@@ -46,3 +46,4 @@ __pycache__/
46 46
47 47 # macOS
48 48 .DS_Store
49 +assets/icon/AppIcon.iconset/
added assets/icon/zyquo-mlx-anvil.svg +75 −0
@@ -0,0 +1,75 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + zyquo-mlx-anvil.svg
4 + Zyquo MLX
5 +
6 + Author: Simon-Pierre Boucher
7 + Mail: contact@spboucher.ai
8 +
9 + Direction 1 — "Z-anvil/spark": the molten copper Z forged above a minimal
10 + anvil, a restrained spark-glow rising behind its lower stroke.
11 +-->
12 +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
13 + <defs>
14 + <!-- Big Sur squircle-ish mask -->
15 + <clipPath id="squircle">
16 + <rect x="0" y="0" width="1024" height="1024" rx="228" ry="228"/>
17 + </clipPath>
18 + <!-- Deep slate forge background -->
19 + <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
20 + <stop offset="0" stop-color="#243449"/>
21 + <stop offset="0.55" stop-color="#1E293B"/>
22 + <stop offset="1" stop-color="#0F172A"/>
23 + </linearGradient>
24 + <!-- Molten copper Z -->
25 + <linearGradient id="copper" x1="0" y1="0" x2="0" y2="1">
26 + <stop offset="0" stop-color="#F0813F"/>
27 + <stop offset="0.45" stop-color="#EA6A2B"/>
28 + <stop offset="1" stop-color="#C2410C"/>
29 + </linearGradient>
30 + <!-- Thin bright rim for the Z -->
31 + <linearGradient id="rim" x1="0" y1="0" x2="0" y2="1">
32 + <stop offset="0" stop-color="#FFC9A3"/>
33 + <stop offset="1" stop-color="#E8703A"/>
34 + </linearGradient>
35 + <!-- Molten glow at the base -->
36 + <radialGradient id="glow" cx="0.5" cy="0.78" r="0.55">
37 + <stop offset="0" stop-color="#EA6A2B" stop-opacity="0.55"/>
38 + <stop offset="0.5" stop-color="#C2410C" stop-opacity="0.22"/>
39 + <stop offset="1" stop-color="#C2410C" stop-opacity="0"/>
40 + </radialGradient>
41 + </defs>
42 +
43 + <g clip-path="url(#squircle)">
44 + <rect width="1024" height="1024" fill="url(#bg)"/>
45 +
46 + <!-- restrained molten glow rising from the anvil -->
47 + <rect width="1024" height="1024" fill="url(#glow)"/>
48 +
49 + <!-- minimal anvil, dim copper-slate, small so the Z dominates -->
50 + <g opacity="0.55">
51 + <path d="M 342 806
52 + L 682 806
53 + Q 700 806 700 824 L 700 836 Q 700 854 682 854 L 596 854
54 + L 620 886 Q 626 896 614 896 L 410 896 Q 398 896 404 886 L 428 854
55 + L 342 854 Q 324 854 324 836 L 324 824 Q 324 806 342 806 Z"
56 + fill="#3E4A5E"/>
57 + <rect x="452" y="854" width="120" height="14" fill="#2C374A"/>
58 + </g>
59 +
60 + <!-- THE Z — dominant, opaque, razor-sharp, with a thin bright rim -->
61 + <g>
62 + <path id="zpath" d="M 268 218
63 + L 756 218
64 + Q 782 218 782 244 L 782 306
65 + Q 782 322 772 334 L 424 726 L 754 726
66 + Q 780 726 780 752 L 780 800
67 + Q 780 826 754 826 L 270 826
68 + Q 244 826 244 800 L 244 738
69 + Q 244 722 254 710 L 602 318 L 270 318
70 + Q 244 318 244 292 L 244 244
71 + Q 244 218 268 218 Z"
72 + fill="url(#copper)" stroke="url(#rim)" stroke-width="7"/>
73 + </g>
74 + </g>
75 +</svg>
added assets/icon/zyquo-mlx-node.svg +66 −0
@@ -0,0 +1,66 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + zyquo-mlx-node.svg
4 + Zyquo MLX
5 +
6 + Author: Simon-Pierre Boucher
7 + Mail: contact@spboucher.ai
8 +
9 + Direction 2 — "Z-core-node": the copper Z in front of dim stacked tensor
10 + planes evoking training/compute layers.
11 +-->
12 +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
13 + <defs>
14 + <clipPath id="squircle">
15 + <rect x="0" y="0" width="1024" height="1024" rx="228" ry="228"/>
16 + </clipPath>
17 + <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
18 + <stop offset="0" stop-color="#243449"/>
19 + <stop offset="0.55" stop-color="#1E293B"/>
20 + <stop offset="1" stop-color="#0F172A"/>
21 + </linearGradient>
22 + <linearGradient id="copper" x1="0" y1="0" x2="0" y2="1">
23 + <stop offset="0" stop-color="#F0813F"/>
24 + <stop offset="0.45" stop-color="#EA6A2B"/>
25 + <stop offset="1" stop-color="#C2410C"/>
26 + </linearGradient>
27 + <linearGradient id="rim" x1="0" y1="0" x2="0" y2="1">
28 + <stop offset="0" stop-color="#FFC9A3"/>
29 + <stop offset="1" stop-color="#E8703A"/>
30 + </linearGradient>
31 + <radialGradient id="glow" cx="0.5" cy="0.62" r="0.5">
32 + <stop offset="0" stop-color="#EA6A2B" stop-opacity="0.28"/>
33 + <stop offset="1" stop-color="#C2410C" stop-opacity="0"/>
34 + </radialGradient>
35 + </defs>
36 +
37 + <g clip-path="url(#squircle)">
38 + <rect width="1024" height="1024" fill="url(#bg)"/>
39 +
40 + <!-- dim stacked tensor planes (training layers), low contrast -->
41 + <g opacity="0.5">
42 + <rect x="242" y="700" width="540" height="34" rx="17" fill="#2C374A"/>
43 + <rect x="282" y="762" width="460" height="30" rx="15" fill="#26303F"/>
44 + <rect x="322" y="818" width="380" height="26" rx="13" fill="#212A37"/>
45 + <!-- faint node dots on the top plane -->
46 + <circle cx="330" cy="717" r="9" fill="#55647E"/>
47 + <circle cx="512" cy="717" r="9" fill="#55647E"/>
48 + <circle cx="694" cy="717" r="9" fill="#55647E"/>
49 + </g>
50 +
51 + <rect width="1024" height="1024" fill="url(#glow)"/>
52 +
53 + <!-- THE Z — dominant, opaque, in front -->
54 + <path d="M 268 190
55 + L 756 190
56 + Q 782 190 782 216 L 782 278
57 + Q 782 294 772 306 L 424 662 L 754 662
58 + Q 780 662 780 688 L 780 736
59 + Q 780 762 754 762 L 270 762
60 + Q 244 762 244 736 L 244 674
61 + Q 244 658 254 646 L 602 290 L 270 290
62 + Q 244 290 244 264 L 244 216
63 + Q 244 190 268 190 Z"
64 + fill="url(#copper)" stroke="url(#rim)" stroke-width="7"/>
65 + </g>
66 +</svg>
added assets/icon/zyquo-mlx-small.svg +46 −0
@@ -0,0 +1,46 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + zyquo-mlx-small.svg
4 + Zyquo MLX
5 +
6 + Author: Simon-Pierre Boucher
7 + Mail: contact@spboucher.ai
8 +
9 + Simplified 16/32 px variant: the copper Z alone (anvil dropped, rim
10 + thickened) so it stays razor-sharp at menu-bar sizes.
11 +-->
12 +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
13 + <defs>
14 + <clipPath id="squircle">
15 + <rect x="0" y="0" width="1024" height="1024" rx="228" ry="228"/>
16 + </clipPath>
17 + <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
18 + <stop offset="0" stop-color="#243449"/>
19 + <stop offset="1" stop-color="#0F172A"/>
20 + </linearGradient>
21 + <linearGradient id="copper" x1="0" y1="0" x2="0" y2="1">
22 + <stop offset="0" stop-color="#F0813F"/>
23 + <stop offset="1" stop-color="#C2410C"/>
24 + </linearGradient>
25 + <radialGradient id="glow" cx="0.5" cy="0.72" r="0.6">
26 + <stop offset="0" stop-color="#EA6A2B" stop-opacity="0.35"/>
27 + <stop offset="1" stop-color="#C2410C" stop-opacity="0"/>
28 + </radialGradient>
29 + </defs>
30 +
31 + <g clip-path="url(#squircle)">
32 + <rect width="1024" height="1024" fill="url(#bg)"/>
33 + <rect width="1024" height="1024" fill="url(#glow)"/>
34 + <path d="M 250 152
35 + L 774 152
36 + Q 802 152 802 180 L 802 264
37 + Q 802 282 791 295 L 448 684 L 772 684
38 + Q 800 684 800 712 L 800 844
39 + Q 800 872 772 872 L 250 872
40 + Q 222 872 222 844 L 222 760
41 + Q 222 742 233 729 L 576 340 L 252 340
42 + Q 224 340 224 312 L 224 180
43 + Q 224 152 250 152 Z"
44 + fill="url(#copper)" stroke="#FFB98A" stroke-width="14"/>
45 + </g>
46 +</svg>
added assets/icon/zyquo-mlx.svg +76 −0
@@ -0,0 +1,76 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + zyquo-mlx.svg
4 + Zyquo MLX
5 +
6 + Author: Simon-Pierre Boucher
7 + Mail: contact@spboucher.ai
8 +
9 + Final icon — "Z-anvil/spark": the molten copper Z forged above a minimal
10 + anvil, a restrained spark-glow rising behind its lower stroke. The Z is the
11 + dominant, opaque focal element (~55%) with a thin bright rim.
12 +-->
13 +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
14 + <defs>
15 + <clipPath id="squircle">
16 + <rect x="0" y="0" width="1024" height="1024" rx="228" ry="228"/>
17 + </clipPath>
18 + <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
19 + <stop offset="0" stop-color="#243449"/>
20 + <stop offset="0.55" stop-color="#1E293B"/>
21 + <stop offset="1" stop-color="#0F172A"/>
22 + </linearGradient>
23 + <linearGradient id="copper" x1="0" y1="0" x2="0" y2="1">
24 + <stop offset="0" stop-color="#F0813F"/>
25 + <stop offset="0.45" stop-color="#EA6A2B"/>
26 + <stop offset="1" stop-color="#C2410C"/>
27 + </linearGradient>
28 + <linearGradient id="rim" x1="0" y1="0" x2="0" y2="1">
29 + <stop offset="0" stop-color="#FFC9A3"/>
30 + <stop offset="1" stop-color="#E8703A"/>
31 + </linearGradient>
32 + <radialGradient id="glow" cx="0.5" cy="0.8" r="0.6">
33 + <stop offset="0" stop-color="#EA6A2B" stop-opacity="0.5"/>
34 + <stop offset="0.5" stop-color="#C2410C" stop-opacity="0.2"/>
35 + <stop offset="1" stop-color="#C2410C" stop-opacity="0"/>
36 + </radialGradient>
37 + </defs>
38 +
39 + <g clip-path="url(#squircle)">
40 + <rect width="1024" height="1024" fill="url(#bg)"/>
41 +
42 + <!-- restrained molten glow rising from the anvil -->
43 + <rect width="1024" height="1024" fill="url(#glow)"/>
44 +
45 + <!-- minimal anvil: horn, face, waist, base — crisp, dim copper-slate -->
46 + <g>
47 + <!-- face + horn -->
48 + <path d="M 368 774
49 + L 664 774
50 + Q 676 774 676 786 L 676 806
51 + Q 676 818 664 818 L 606 818
52 + L 586 846 L 486 846 L 466 818 L 430 818
53 + Q 386 816 356 800 Q 344 793 356 786 Q 372 777 368 774 Z"
54 + fill="#46536A"/>
55 + <!-- waist + base -->
56 + <path d="M 486 846 L 586 846 L 596 862 L 476 862 Z" fill="#39455A"/>
57 + <path d="M 452 862 L 620 862 Q 632 862 632 874 L 632 884 Q 632 892 622 892 L 450 892 Q 440 892 440 884 L 440 874 Q 440 862 452 862 Z"
58 + fill="#2E394C"/>
59 + <!-- faint hot line on the face where the Z was forged -->
60 + <rect x="486" y="780" width="130" height="7" rx="3.5" fill="#C2410C" opacity="0.7"/>
61 + </g>
62 +
63 + <!-- THE Z — dominant, opaque, razor-sharp, thin bright rim -->
64 + <path d="M 268 172
65 + L 756 172
66 + Q 782 172 782 198 L 782 260
67 + Q 782 276 772 288 L 424 664 L 754 664
68 + Q 780 664 780 690 L 780 730
69 + Q 780 756 754 756 L 270 756
70 + Q 244 756 244 730 L 244 668
71 + Q 244 652 254 640 L 602 264 L 270 264
72 + Q 244 264 244 238 L 244 198
73 + Q 244 172 268 172 Z"
74 + fill="url(#copper)" stroke="url(#rim)" stroke-width="7"/>
75 + </g>
76 +</svg>
modified docs/PLAN.md +7 −1
@@ -137,7 +137,13 @@ workbench shell renders the real Phase 3 artifacts (4 models incl. the fused
137 137 forge model, 1 dataset, 3 runs) with live MemoryAdvisor verdicts. Run
138 138 configurator, live loss charts, playground interactions, and Hub Discover are
139 139 Phase 6 features and will be built on this spec.
140 ## Phase 5 — App Icon (not started)
140 +## Phase 5 — App Icon ✅ (completed 2026-07-30)
141 +
142 +- [x] Two SVG directions rendered and compared: **Z-anvil/spark chosen** (stronger forge story via glow + anvil); Z-core-node kept in assets for reference
143 +- [x] Refined: crisp geometric anvil (horn/face/waist/base + hot copper line), Z lifted for breathing room, restrained base glow; reviewed at 512 + zoom
144 +- [x] Simplified small variant (Z only, thicker rim) for 16/32 px
145 +- [x] `make icon` (scripts/make-icon.sh): rsvg-convert → full iconset (16→1024 incl @2x, small variant ≤32) → `iconutil` → AppIcon.icns; embedded via `make app`
146 +- [x] Phase checkpoint: size-ladder review 16→256 sharp; verified in the real Dock — unmistakably the copper Zyquo sibling
141 147 ## Phase 6 — Features (not started)
142 148 ## Phase 7 — Verification (not started)
143 149 ## Phase 8 — Signing & Notarization (not started)
added scripts/make-icon.sh +44 −0
@@ -0,0 +1,44 @@
1 +#!/bin/bash
2 +#
3 +# make-icon.sh
4 +# Zyquo MLX
5 +#
6 +# Author: Simon-Pierre Boucher
7 +# Mail: contact@spboucher.ai
8 +#
9 +# Icon pipeline (charter Phase 5): SVG → PNGs → AppIcon.iconset →
10 +# AppIcon.icns. The SVG is the source of truth; 16/32 px sizes use the
11 +# simplified variant (Z only) for sharpness.
12 +#
13 +set -euo pipefail
14 +
15 +cd "$(dirname "$0")/.."
16 +SRC=assets/icon/zyquo-mlx.svg
17 +SRC_SMALL=assets/icon/zyquo-mlx-small.svg
18 +ICONSET=assets/icon/AppIcon.iconset
19 +OUT=assets/icon/AppIcon.icns
20 +
21 +command -v rsvg-convert >/dev/null || { echo "error: rsvg-convert missing (brew install librsvg)"; exit 1; }
22 +
23 +rm -rf "$ICONSET"
24 +mkdir -p "$ICONSET"
25 +
26 +render() { # $1 svg, $2 px, $3 name
27 + rsvg-convert -w "$2" -h "$2" "$1" -o "$ICONSET/$3"
28 +}
29 +
30 +# Small sizes: simplified variant
31 +render "$SRC_SMALL" 16 icon_16x16.png
32 +render "$SRC_SMALL" 32 icon_16x16@2x.png
33 +render "$SRC_SMALL" 32 icon_32x32.png
34 +# 64 px and up: full anvil artwork
35 +render "$SRC" 64 icon_32x32@2x.png
36 +render "$SRC" 128 icon_128x128.png
37 +render "$SRC" 256 icon_128x128@2x.png
38 +render "$SRC" 256 icon_256x256.png
39 +render "$SRC" 512 icon_256x256@2x.png
40 +render "$SRC" 512 icon_512x512.png
41 +render "$SRC" 1024 icon_512x512@2x.png
42 +
43 +iconutil -c icns "$ICONSET" -o "$OUT"
44 +echo "→ $OUT"
45