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%
30.6 KB

# CLAUDE.md — Zyquo MLX

# Project Identity

Zyquo MLX is the foundry member of the Zyquo family: a legendary, native macOS app written in Swift + SwiftUI, built without the Xcode IDE (Swift Package Manager + command-line toolchain where the MLX/Metal toolchain allows). Where Zyquo Local is a consumer chat client for downloaded MLX models, Zyquo MLX is the power-user foundry: a complete workbench for the full on-device MLX lifecycle on Apple Silicon — inference of every supported model type, fine-tuning (LoRA/QLoRA and full), quantization, format conversion, dataset preparation, training runs with live metrics, evaluation, and export.

Think "the local MLX studio for the Mac": pull or point at any model, run it (LLM, VLM, embeddings, and whatever else the current MLX ecosystem supports), fine-tune it on your own data with a real training UI, quantize/convert it, evaluate it, and ship the result — all locally, all Apple-Silicon-native, all beautiful.

Naming conventions (use consistently everywhere):

  • Display name / product name: Zyquo MLX
  • App bundle: Zyquo MLX.app
  • Bundle identifier: com.zyquo.mlx
  • Executable / SPM target: ZyquoMLX (no space)
  • Data folder: ~/Library/Application Support/ZyquoMLX/
  • Models: ~/Library/Application Support/ZyquoMLX/Models/
  • Datasets: ~/Library/Application Support/ZyquoMLX/Datasets/
  • Training runs / checkpoints: ~/Library/Application Support/ZyquoMLX/Runs/
  • Repo module prefix in file headers: Zyquo MLX
  • Platform: Apple Silicon (arm64) ONLY. MLX requires Apple Silicon. Detect Intel at launch and show a clear, polite unsupported-hardware screen.

# 📋 MANDATORY FILE HEADER — EVERY CODE FILE

Every single code file you write (all .swift files, plus Makefile, shell scripts, Package.swift, any Python training helper scripts if used, verification scripts — anything containing code) MUST begin with this header comment, adapted to the file's comment syntax:

swift
//
//  <FileName>.swift
//  Zyquo MLX
//
//  Author: Simon-Pierre Boucher
//  Mail: contact@spboucher.ai
//

For shell / Python / Makefiles:

bash
#
#  <filename>
#  Zyquo MLX
#
#  Author: Simon-Pierre Boucher
#  Mail: contact@spboucher.ai
#

No exceptions. If you ever create or refactor a file and the header is missing, add it. Before declaring the project done, run a sweep over the repository to verify every code file carries the header.


# 🧭 METHODOLOGY — WORK METHODICALLY, KEEP EVERYTHING COHERENT

You must execute this project strictly in phase order (0 → 8). Do not jump ahead, do not interleave phases, do not build the fine-tuning UI before an inference run works end-to-end, and do not write any code before Phase 0 research is complete.

Working rules:

  1. One phase at a time. At the start of each phase, write a checklist into docs/PLAN.md; check items off as you go. At the end of each phase, run a phase checkpoint: build (swift build), run what's runnable, fix all warnings/errors, write a 3–5 line phase summary in docs/PLAN.md before moving on.
  2. Phase gates: Phase 0 is complete only when docs/MLX-RESEARCH.md (framework), docs/TRAINING-RESEARCH.md (fine-tuning), and docs/BUILD.md (no-Xcode-IDE build recipe incl. Metal) are complete. Phase 2 is complete only when a CLI POC runs inference on one small model of at least two types. Phase 3 is complete only when a real LoRA fine-tune completes on a tiny dataset and the adapted model generates. Phase 4 spec is the contract for all UI in Phase 6. Phase 7 is complete only when the multi-capability verification table is green. Phase 8 is complete only when spctl says "Notarized Developer ID".
  3. Single source of truth, everywhere:
    • MLX capabilities/APIs → only as documented in Phase 0 docs; never guess an API name.
    • Curated model/dataset data → only from Catalog (generated from Phase 0). Live Hugging Face results come from HubService only.
    • Colors, fonts, spacing, radii → only from ZyquoTheme design tokens. Zero raw hex or magic numbers in views.
    • Inference, training, quantization, conversion → only in the Engine/, Training/, Convert/ layers; never leak into Views/ViewModels.
    • Product naming → per the conventions above. Never Zyquo alone, never ZyquoMLX in user-facing text.
  4. Coherence sweeps: after Phases 3, 6, and 8 (uniform naming — always LocalModel, TrainingRun, Dataset, Checkpoint; no dead code; headers present; folders match Phase 2).
  5. Compile early, compile often. Never accumulate more than one file of unbuilt changes.
  6. Commit discipline: one logical unit per commit, phase-prefixed. Never commit model weights, datasets, or checkpoints (add them to .gitignore).
  7. Long-running work is first-class: training/quantization can run for minutes to hours. From the first training code, build for cancellable, resumable, observable background jobs with persisted state — not fire-and-forget.

# ⚠️ PHASE 0 — MANDATORY INTENSIVE WEB RESEARCH (DO THIS FIRST, BEFORE ANY CODE)

Do NOT rely on training data — MLX moves fast. Perform several intensive web research sessions on the current MLX ecosystem and produce three documents. Use official sources: github.com/ml-explore/mlx, github.com/ml-explore/mlx-swift, github.com/ml-explore/mlx-swift-examples, github.com/ml-explore/mlx-examples (Python: LoRA/LLMS/whisper/stable-diffusion/etc.), ml-explore.github.io/mlx docs, github.com/ml-explore/mlx-lm, huggingface.co/mlx-community, github.com/huggingface/swift-transformers.

# 0.A — docs/MLX-RESEARCH.md — the MLX framework, deeply

Document precisely and completely:

  1. What MLX is and its core primitives: the array framework, lazy evaluation & eval(), unified-memory model on Apple Silicon, streams/devices (GPU/CPU), mlx.core, mlx.nn, mlx.optimizers, automatic differentiation (value_and_grad), and how compute is dispatched to Metal.
  2. MLX Swift vs. MLX Python — the honest capability split. Determine CURRENT reality: MLX has a mature Python stack (mlx-lm, mlx-examples for LoRA fine-tuning, quantization, VLM, whisper, stable diffusion) and a Swift stack (mlx-swift, mlx-swift-examples with MLXLLM/MLXVLM/MLXLMCommon, MLXNN, MLXOptimizers, MLXRandom). Document exactly which capabilities exist natively in Swift today (inference for LLM/VLM/embeddings, training primitives, LoRA) vs. which are Python-first (full fine-tuning pipelines, quantization tooling, conversion, some model types). This determines the app's execution strategy (see 0.A.6).
  3. Model types & the current MLX model zoo. Document what MLX supports RIGHT NOW: text LLMs (Llama, Qwen2/2.5/3, Mistral, Gemma/2/3, Phi, DeepSeek/distills, SmolLM…), vision-language models (Qwen-VL, LLaVA, Idefics, Pixtral, etc. via MLXVLM / mlx-vlm), embeddings, speech (Whisper via mlx-examples), image generation (Stable Diffusion / FLUX via mlx-examples), and any others. For each type: which package handles it, the exact load/run APIs, and input/output formats.
  4. Inference API specifics (Swift-first, Python fallback): loading a model dir (ModelContainer/factory APIs — verify names), tokenizers & chat templates, streaming generation (AsyncSequence/callback), generation params (temp, topP, repetitionPenalty, maxTokens, seed), KV-cache, and unloading/freeing memory (MLX.GPU.set(cacheLimit:), memory APIs).
  5. Quantization & conversion: how MLX quantizes weights (group size, bits — 4/8-bit, nf4-style?), the mlx_lm.convert / conversion tools to turn HF models into MLX format, and how to quantize during/after conversion. Document exact commands/APIs and the resulting on-disk format (config.json, *.safetensors sharding, model.safetensors.index.json, tokenizer files, quantization metadata).
  6. ⚠️ Build & execution strategy — resolve definitively and document in docs/BUILD.md:
    • Verify whether swift build compiles MLX's Metal kernels with only Command Line Tools or needs the full Xcode Metal toolchain. Test it. If full Xcode's metal compiler is required, the rule adapts to command-line swift build/xcodebuild only, no Xcode IDE, no hand-authored .xcodeproj, fully automated by the Makefile.
    • Decide the execution model for capabilities that are Python-first (likely full fine-tuning, quantization, conversion, image/audio): the app ships/manages a controlled embedded Python environment (e.g., a bundled venv using mlx-lm/mlx Python packages) that the Swift app drives via Process for those pipelines, while doing native-Swift MLX for LLM/VLM inference and LoRA where Swift supports it. Document how the venv is created/bootstrapped on first run (uv/pip), pinned versions, offline behavior, and how progress/metrics are streamed back to Swift (parse stdout / a JSON progress protocol). If, by the time you build, Swift natively supports a capability, prefer Swift and note it.
  7. Memory & performance: estimating RAM for inference vs. training (weights + optimizer state + activations + KV cache), batching, gradient checkpointing if available, and realistic model-size limits per Mac RAM tier.

# 0.B — docs/TRAINING-RESEARCH.md — fine-tuning on MLX, concretely

  1. LoRA / QLoRA on MLX: the exact mlx-lm/mlx-examples LoRA workflow — command/API surface, hyperparameters (rank, alpha, dropout, learning rate, batch size, iters/epochs, target modules, quantized base for QLoRA), how adapters are saved (adapters.safetensors), and how to fuse an adapter back into base weights.
  2. Full fine-tuning: feasibility, memory cost, and the workflow/limits on Apple Silicon.
  3. Datasets: the expected dataset formats (JSONL chat format, completion format, prompt/response), train/valid split, how prompts are templated, tokenization, and validation. Document at least the standard {"messages": [...]} and {"prompt":..., "completion":...} shapes MLX expects.
  4. Training loop observability: what metrics are emitted (train/val loss, tokens/sec, iteration, learning rate), checkpoint cadence, and how to resume from a checkpoint.
  5. Evaluation: perplexity/loss on a held-out set, quick qualitative generation checks, and comparing base vs. fine-tuned.

# 0.C — docs/MODELS.md — curated catalog + Hub integration

  • Hugging Face Hub HTTP API (search, model info/file listing, resolve URLs, LFS, sizes, optional HF token for gated models) — same rigor as Zyquo Local.
  • A curated Featured catalog across types and sizes (text, VLM, embeddings, speech, image-gen where applicable) with exact mlx-community repo IDs, sizes, quant, and min-RAM — verified to exist right now.
  • A RAM table (8/16/24/32/48/64/128 GB) for inference and for LoRA fine-tuning (training needs more) to power in-app compatibility badges.

# PHASE 1 — Project Setup

  • Toolchain: SPM (Package.swift, target ZyquoMLX) depending on the MLX Swift packages from Phase 0. Build per docs/BUILD.md.
  • Embedded Python (if Phase 0.A.6 requires it): Makefile target that provisions a pinned, isolated venv under ~/Library/Application Support/ZyquoMLX/py/ (mlx, mlx-lm, and needed extras), created on first launch with clear UI progress; never pollute the user's system Python.
  • App bundle: Makefile builds release, assembles Zyquo MLX.app (binary, Info.plist, Resources/AppIcon.icns, any MLX metallib/resource bundles, and any bundled Python bootstrap assets), signs (Phase 8; ad-hoc for make dev).
  • Info.plist: CFBundleDisplayName = Zyquo MLX, bundle ID com.zyquo.mlx, LSMinimumSystemVersion per MLX (set from Phase 0), NSHighResolutionCapable, LSApplicationCategoryType (public.app-category.developer-tools), LSArchitecturePriority arm64.
  • Entry point: @main SwiftUI App; Apple-Silicon gate; proper activation from terminal.
  • Dependencies: MLX Swift packages + swift-transformers (if chosen) + Apple swift-markdown (optional). Nothing else in Swift; Python side pinned in the venv.

# PHASE 2 — Architecture + Inference POC (All Types)

text
Sources/ZyquoMLX/
├── App/                    # @main, windows, Apple-Silicon gate, first-run bootstrap
├── DesignSystem/           # ZyquoTheme — family tokens, MLX foundry palette
├── Models/                 # LocalModel, ModelType, Dataset, TrainingRun, Checkpoint, Job…
├── Engine/
│   ├── InferenceEngine.swift   # actor: load/run per model type (LLM/VLM/embeddings), streaming
│   ├── ModelTypeAdapters.swift # LLM, VLM, Embeddings, (Speech/ImageGen via Py bridge)
│   ├── GenerationParams.swift
│   └── MemoryAdvisor.swift     # RAM estimates for inference AND training
├── Training/
│   ├── TrainingService.swift   # orchestrates LoRA/QLoRA/full runs (Swift or Py bridge)
│   ├── HyperParams.swift
│   ├── RunStore.swift          # runs, checkpoints, resume, metrics history
│   └── MetricsStream.swift     # live loss/tok-per-sec/LR parsing
├── Convert/
│   ├── ConversionService.swift # HF→MLX convert, quantize, fuse adapters, export
│   └── QuantConfig.swift
├── Data/
│   ├── DatasetService.swift    # import/validate/split JSONL, preview, templating
│   └── DatasetFormats.swift
├── Hub/
│   ├── HubService.swift        # HF search/info/files
│   ├── DownloadManager.swift   # resumable, progress
│   └── ModelStore.swift        # local library scan/validate/delete
├── PyBridge/                   # only if Phase 0.A.6 requires Python for some pipelines
│   ├── PythonRunner.swift      # Process wrapper over the venv, JSON progress protocol
│   └── scripts/                # pinned helper scripts (train.py, convert.py, quantize.py…)
├── Services/
│   ├── PersistenceService.swift
│   └── Catalog.swift           # curated Featured catalog from docs/MODELS.md
├── ViewModels/
└── Views/
  • InferenceEngine is an actor, dispatching by ModelType. Native Swift MLX for LLM/VLM/embeddings; Py bridge only where Phase 0 proved necessary.
  • PHASE GATE: CLI POC (ZyquoMLX --infer <model-dir> ...) runs inference on at least two model types (e.g., a small text LLM streaming tokens + an embedding model returning vectors, and a VLM on an image if feasible) with final stats.

# PHASE 3 — TRAINING, QUANTIZATION & CONVERSION (THE FOUNDRY CORE)

Build the full lifecycle. PHASE GATE: a real LoRA fine-tune completes on a tiny sample dataset, emits live loss, saves an adapter, the adapter fuses into the base, and the adapted model generates visibly different output — all driven from the app.

# 3.A — Datasets (DatasetService)

  • Import JSONL/CSV; validate against MLX's expected formats (chat {"messages":[…]} and prompt/completion); auto train/valid split; preview samples with the applied chat template; report token stats and any malformed rows with fixes.

# 3.B — Training (TrainingService, RunStore, MetricsStream)

  • Configure and launch LoRA / QLoRA (and full fine-tuning where feasible) with a clear hyperparameter form (rank, alpha, dropout, LR, batch size, iters/epochs, target modules, max seq len, seed), grounded in docs/TRAINING-RESEARCH.md.
  • Runs are cancellable, resumable background jobs with persisted state; checkpoints saved on cadence; live metrics (train/val loss curves, tokens/sec, LR, ETA) streamed to the UI.
  • Whether executed natively (Swift MLX) or via the Py bridge, expose a uniform TrainingRun API + a clean JSON progress protocol.
  • MemoryAdvisor gates configs that won't fit this Mac's RAM and suggests QLoRA / smaller rank / smaller base.

# 3.C — Quantization, conversion, fusion, export (ConversionService)

  • Convert HF models → MLX format; quantize (bits/group size per Phase 0) with size/RAM preview; fuse LoRA adapters into base weights; export a ready-to-run MLX model directory (and optionally push/save for use in Zyquo Local).
  • Every conversion/quant job is a tracked, cancellable background job with progress and a clear before/after size + validation step.

# PHASE 4 — DESIGN SYSTEM & UI (LIGHT THEME, PIXEL-PERFECT, "FOUNDRY" IDENTITY)

Same design DNA and ZyquoTheme token system as the family, with an "MLX foundry" identity: technical, precise, a workbench for pros. Palette is a molten copper-on-slate story (forge/foundry) balanced to stay clean and Apple-like.

# 4.1 — Light theme

Token Value (light) Usage
background #FAFAF9 (warm neutral off-white) Canvas
surface #FFFFFF Cards, panels
surfaceSecondary #F3F2F0 Hover, code/log blocks
accent #C2410C#EA6A2B (molten copper) paired with slate #334155 Primary actions, run/train buttons, active states
accentSubtle #FCEDE4 Selected rows, active-run tint
textPrimary #1A1A1C · textSecondary #6B6B72 · textTertiary #9E9EA6 · border #E6E4E1
success/warning/danger #2FA36B/#D9822B/#D64545 Job ok / caution / failed
chart tokens copper (train loss), slate (val loss), teal (tok/s) Metric curves

Family rules apply (no pure black on white, 0.5pt hairlines, ultra-soft shadows on floating panels only, dark theme derived — a deep slate forge feel; light theme is flagship). Typography/spacing/radii identical to the family; SF Mono for logs/metrics/code. Data-dense views are allowed to be denser than the chat apps, but must stay clean and aligned.

# 4.2 — Layout & screens (exact spec)

A workbench with a left navigator (not a chat-first layout). Default 1360×880, min 1080×700.

  • Left navigator (240pt, translucent): sections — Models (local library + Discover), Datasets, Train (runs), Convert (jobs), Playground (inference), Evaluate. Footer: settings gear, active-job indicator (spinner + count), current RAM/GPU usage readout.
  • Models: Installed grid/list (name, type badge LLM/VLM/Embed/Speech/Image, params, quant, disk size, RAM verdict for inference & training) + Discover (live Hub search scoped to mlx-community, filters by type/size/quant, resumable downloads with progress). Actions: run in Playground, use as train base, convert/quantize, delete, reveal in Finder.
  • Datasets: import, validate, preview with template applied, split config, token stats; per-dataset detail with sample browser and error report.
  • Train: a run configurator (base model picker with RAM gating, method LoRA/QLoRA/Full, dataset picker, hyperparameter form with inline explanations and sane defaults, estimated memory & time) → Start. A run detail screen with live loss chart (train/val), tokens/sec, iteration/ETA, LR schedule, a streaming log console (SF Mono), checkpoint list, and Pause/Resume/Cancel. A runs list showing history with status pills.
  • Convert: pick a model → convert to MLX / quantize (bits, group size) / fuse adapter / export; job cards with progress, before/after size, validation result, and "send to Zyquo Local".
  • Playground (inference): load any local model by type and interact — for LLM/VLM a streaming chat with images for VLM; for embeddings a text→vector inspector with similarity demo; for speech a transcription panel; for image-gen a prompt→image panel (only for types MLX supports). Per-run stats (tok/s, TTFT, memory). A compare mode to run base vs. fine-tuned side by side.
  • Evaluate: run held-out loss/perplexity and qualitative prompts on base vs. fine-tuned; show a compact scorecard.
  • Header (52pt): contextual to the section; shows active model/run/job chip, memory dot, and quick actions.
  • Empty states: each section has a beautiful, instructive empty state (first model, first dataset, first run) — must look intentional, App-Store-front-page quality.

Settings (native tabs, 760×560): 1. General (default paths, keep-loaded) 2. Compute (GPU cache limit, thread/stream options MLX exposes, memory ceiling) 3. Python Environment (venv status/version, reinstall/repair, pinned package versions, offline mode) — only if Py bridge used 4. Storage (models/datasets/runs locations, disk usage, cleanup) 5. Hugging Face (token, masked) 6. Appearance (Light/Dark/System; accent: copper default + slate, sky, emerald, violet; font size) 7. Shortcuts 8. Advanced (reveal data folder, export logs).

# 4.3 — Motion & 4.4 quality gate

Family motion standard; foundry-specific: loss charts animate smoothly as points stream (no reflow jank), log console autoscrolls with a jump-to-bottom pill, job progress never jumps. Quality gate: review every state — no models, downloading, loading, inferring, training (with live metrics), paused, resuming, cancelled, failed (OOM → suggest QLoRA/smaller), converting, quantizing, Python env installing/repairing. Consistent tokens, aligned baselines, no clipped logs, correct dark mode, clean scaling. If it looks "developer-made", iterate.


# PHASE 5 — APP ICON: ULTRA-LEGENDARY "FOUNDRY" ICON, DESIGNED IN SVG

Designed in SVG first (assets/icon/zyquo-mlx.svg) → .icns. Sibling of Cloud/Local/Agent/Atlas: same squircle, same dominant Z DNA, same premium quality — telling the MLX foundry / forge / build story. Apply the family readability rule: the Z is the dominant, opaque, highest-contrast focal element (~55%) with a thin contrasting rim so it never blends into glow.

Creative direction — the Z that forges. Two directions (render both, keep the best):

  1. Z-anvil/spark: the bold Z as the hero, with a subtle forge spark / molten glow rising behind its lower stroke and a minimal anvil-like base beneath — kept small and dim so the Z dominates. Reads as "where models are forged".
  2. Z-core-node: the Z centered over a subtle neural/graph node or layered-tensor motif (thin stacked planes) evoking training/compute — low-contrast backdrop, Z in front.
  • Canvas: Big Sur squircle (Apple curvature).
  • Palette (mirrors the app): deep slate gradient background (#1E293B → #0F172A) with a molten copper Z (#EA6A2B → #C2410C) carrying a thin bright rim and a restrained glow only at the base (the "molten" hint), so the Z stays razor-sharp and clearly foreground; the supporting motif (spark/anvil or node planes) is a dim copper-slate. Distinct from Cloud (sky), Local (emerald silicon), Agent (violet), Atlas (teal-indigo), yet unmistakably the same family.
  • Precision & iteration: clean paths, viewBox="0 0 1024 1024", optical centering, effects that survive downscaling; render 16→1024, inspect, refine; simplified small-size variant (drop base motif, keep the copper Z) for 16/32px.

Pipeline (Makefile): SVG → PNGs (16→1024 incl. @2x) via rsvg-convert or CoreGraphics rasterizer → AppIcon.iconseticonutil -c icns. SVG stays as source of truth. Derive the monochrome menu-bar template glyph and in-app wordmark from the same SVG.


# PHASE 6 — Features (This is where Zyquo MLX becomes LEGENDARY)

# Inference (all types)

  • Playground for LLM (streaming chat), VLM (image + text), embeddings (vector + similarity), and — where MLX supports it — speech (transcription) and image generation
  • Per-run stats (tok/s, TTFT, peak memory); base vs. fine-tuned compare; model load/unload with verifiable memory release; MemoryAdvisor verdicts everywhere

# Fine-tuning

  • LoRA / QLoRA / (full where feasible) with a real configurator + inline guidance and RAM gating
  • Cancellable, resumable background training with checkpoints; live loss/val curves, tokens/sec, LR, ETA, and a streaming log console
  • Adapter save + fuse into base; export fine-tuned model

# Quantization / conversion / export

  • HF → MLX conversion; quantize (bits/group size) with size & RAM preview; fuse adapters; validated export; one-click "send to Zyquo Local"

# Data

  • Dataset import/validate/split/preview with template applied; token stats; malformed-row detection & fixes

# Models & Hub

  • In-app Hugging Face browse/search (mlx-community + filters) with resumable downloads; local library management; curated Featured catalog

# Evaluation & polish

  • Held-out loss/perplexity + qualitative eval, base-vs-tuned scorecard
  • Reused encrypted vault pattern for the HF token; export logs/metrics; per-model & per-run notes
  • Shortcuts: ⌘N new run, ⌘I open Playground, ⌘L Models, ⌘D Datasets, ⌘R start/stop run, ⌘F search, ⌥Space quick inference; toggleable menu bar extra showing active-job status

# PHASE 7 — VERIFICATION (MANDATORY)

No API keys — verification means proving the full local MLX lifecycle works end-to-end on this Mac:

  1. Inference matrix: download and run at least one real model per supported type that fits this Mac (text LLM streaming; embeddings returning sane vectors; VLM on an image if supported; speech/image-gen if MLX supports them and RAM allows). Verify correct output, streaming, cancellation, and memory release. Record tok/s and TTFT.
  2. Training: run a real LoRA fine-tune on a small dataset to completion — verify live metrics, checkpointing, resume from checkpoint, adapter save, fuse, and that the fused model generates coherently and differently from base. Run a QLoRA variant. Confirm OOM configs are blocked/warned by MemoryAdvisor.
  3. Convert/quantize: convert an HF model to MLX and quantize it; verify the output loads and runs, with correct before/after sizes.
  4. Catalog & Hub: dry-verify the entire Featured catalog against the live Hub (repo IDs exist, files/sizes match docs/MODELS.md).
  5. Python env (if used): verify clean venv bootstrap on a fresh profile, repair flow, pinned versions, and the JSON progress protocol.
  6. Produce a green results table (capability → model → ✅/❌ → metrics/notes); fix every failure until green. Test artifacts (models/datasets/runs) may be cleaned afterward; keep the smallest for dev.

# PHASE 8 — SIGNING & NOTARIZATION (REAL, NOT AD-HOC)

The user has an existing, working signing/notarization setup for another project. Before doing anything, read and inspect the folder:

text
/Users/simon-pierreboucher/Desktop/other/OTHER/zyquo-term

Locate the Developer ID Application identity name, Team ID, notarytool keychain profile (or Apple ID + app-specific password), entitlements, and any config there. Reuse the exact same identity, Team ID, and notarytool credentials/profile for Zyquo MLX. Never invent placeholders, never print secrets, never commit them.

Then implement make release:

  1. Build release (arm64 only — MLX), assemble Zyquo MLX.app incl. MLX metallibs/resource bundles and any Python bootstrap assets.
  2. entitlements.plist with Hardened Runtime; because MLX may JIT/allocate executable Metal/GPU work and (if used) the app spawns a bundled Python via Process, verify the minimal correct posture — you will likely need Hardened Runtime plus, if truly required by MLX/Python, com.apple.security.cs.allow-jit and/or com.apple.security.cs.allow-unsigned-executable-memory and disable-library-validation for the Python dylibs. Test without them first; add only what's proven necessary, and document why. Do NOT App-Sandbox (this is a local ML workbench needing broad file/compute access) unless the user explicitly asks.
  3. Sign nested code first — this is the classic notarization failure point here: every bundled framework, metallib, and (if bundled) Python interpreter/dylibs/.so files must be signed with Hardened Runtime before signing the app. codesign --force --options runtime --timestamp --entitlements entitlements.plist --sign "Developer ID Application: <identity from zyquo-term>" "Zyquo MLX.app".
  4. ditto -c -k --keepParentxcrun notarytool submit "Zyquo MLX.zip" --keychain-profile "<profile from zyquo-term>" --wait.
  5. xcrun stapler staple "Zyquo MLX.app"; verify spctl -a -vv = "accepted, source=Notarized Developer ID" and stapler validate.
  6. Optional signed+stapled DMG (hdiutil).
  7. On failure: notarytool log, fix (almost always an unsigned nested Python .so/dylib or a missing hardened-runtime flag), resubmit until it passes. Keep make dev (ad-hoc) for iteration. Note: if a bundled Python environment proves impossible to notarize cleanly, document the fallback (first-run provisioning of the venv into Application Support, outside the signed bundle) chosen in Phase 0.A.6.

# Engineering Standards

  • Swift 5.9+ (Swift 6 mode if the toolchain allows); zero warnings
  • InferenceEngine and TrainingService as actors; all Hub/config/metrics types Codable; jobs are cancellable & resumable with persisted state
  • If a Py bridge is used, isolate ALL Python interaction behind PythonRunner with a strict JSON progress protocol; pin versions; never touch system Python
  • Robust, human-readable errors for every failure class (OOM during load/train → suggest QLoRA/smaller/quantize, dataset malformed → show row & fix, unsupported architecture, disk full, venv broken → repair flow, download interrupted → resume)
  • Design tokens only — no hardcoded colors/sizes in views; UI strings centralized
  • README.md (build) + docs/ (MLX-RESEARCH, TRAINING-RESEARCH, BUILD, MODELS, PLAN); .gitignore excludes weights/datasets/checkpoints/venv
  • Commit in logical, phase-prefixed increments

# Definition of Done

  • make release produces a Developer ID–signed, notarized, stapled Zyquo MLX.app (verified by spctl), built without the Xcode IDE
  • Inference works across every MLX-supported model type available today (LLM/VLM/embeddings + speech/image-gen where supported), with streaming and verifiable memory management
  • Real LoRA/QLoRA fine-tuning runs end-to-end with live metrics, checkpoints, resume, adapter fuse, and export; full fine-tuning where feasible
  • Conversion + quantization produce valid MLX models; export + "send to Zyquo Local" works
  • Datasets import/validate/preview correctly; Hub browse + resumable downloads + curated catalog live-verified
  • MemoryAdvisor verdicts are accurate for this machine for both inference and training
  • The copper-on-slate SVG icon exists, is striking at all sizes with the Z clearly dominant and detached from glow, embedded as .icns + template glyph; clearly a sibling of the other Zyquo icons
  • The copper light theme matches the Phase 4 spec and passes the design quality gate; dark theme derived and correct
  • Naming coherent everywhere: Zyquo MLX user-facing, com.zyquo.mlx, ZyquoMLX target/data folder
  • Every code file starts with the mandatory Author/Mail header (verified by a repo-wide sweep)
  • docs/PLAN.md shows every phase completed; the Phase 0 research docs are complete and traceable to the implementation
  • Zyquo MLX feels like a polished, legendary native Mac foundry — the definitive local MLX studio