Bootstrap: charter-compliant skeleton, header enforcement, hardware manifest, experiment scaffolds
- Repository layout per CLAUDE.md §3 - tools/check_headers.py enforcing §0.1 (58 files pass) - tools/new_experiment.py scaffolding with seven-field hypothesis block (§10) - benchmarks/hardware_manifest.py: macOS-native fingerprint (M5 Max / 48GB verified) - Eight micro-experiment scaffolds (§9, exp A–H) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 61 changed files with +2,393 and −0
added
.gitignore
+46 −0
@@ -0,0 +1,46 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : .gitignore | |
| 4 | +# Purpose : Git ignore rules (venvs, caches, large artifacts, OS noise) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +# Python | |
| 14 | +__pycache__/ | |
| 15 | +*.py[cod] | |
| 16 | +.venv/ | |
| 17 | +venv/ | |
| 18 | +*.egg-info/ | |
| 19 | +.pytest_cache/ | |
| 20 | +.ruff_cache/ | |
| 21 | +.mypy_cache/ | |
| 22 | + | |
| 23 | +# macOS | |
| 24 | +.DS_Store | |
| 25 | + | |
| 26 | +# Build artifacts | |
| 27 | +build/ | |
| 28 | +*.metallib | |
| 29 | +*.air | |
| 30 | +*.o | |
| 31 | +*.dylib | |
| 32 | + | |
| 33 | +# Large model files — never commit checkpoints | |
| 34 | +*.safetensors | |
| 35 | +*.gguf | |
| 36 | +*.bin | |
| 37 | +*.pt | |
| 38 | +*.pth | |
| 39 | +models_cache/ | |
| 40 | + | |
| 41 | +# Local editor/session | |
| 42 | +.claude/settings.local.json | |
| 43 | + | |
| 44 | +# Raw traces can be huge; committed results are curated JSON/CSV/plots | |
| 45 | +results/**/*.trace | |
| 46 | +results/**/*.fsusage | |
added
CITATION.cff
+20 −0
@@ -0,0 +1,20 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : CITATION.cff | |
| 4 | +# Purpose : Citation metadata for the research repository | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +cff-version: 1.2.0 | |
| 13 | +message: "If you use this research, please cite it as below." | |
| 14 | +title: "localvm-research: out-of-core execution of large pretrained LLMs on consumer Apple Silicon" | |
| 15 | +authors: | |
| 16 | + - family-names: "Boucher" | |
| 17 | + given-names: "Simon-Pierre" | |
| 18 | + email: "contact@spboucher.ai" | |
| 19 | +date-released: "2026-08-11" | |
| 20 | +version: "0.0.1" | |
added
CLAUDE.md
+781 −0
@@ -0,0 +1,781 @@ | ||
| 1 | +# CLAUDE.md | |
| 2 | + | |
| 3 | +**Project codename:** `localvm-research` (provisional — final name decided by evidence, not preference) | |
| 4 | +**Principal investigator / Author:** Simon-Pierre Boucher — <contact@spboucher.ai> | |
| 5 | +**Primary platform:** Apple Silicon Mac (macOS 14+) | |
| 6 | +**Document status:** Living research charter. Claude must treat this as the authoritative project specification. | |
| 7 | + | |
| 8 | +--- | |
| 9 | + | |
| 10 | +## 0. Administrative conventions (MANDATORY — read before anything else) | |
| 11 | + | |
| 12 | +### 0.1 Author header requirement | |
| 13 | + | |
| 14 | +**Every single source file created in this project — without exception — must begin with a standardized author header.** | |
| 15 | + | |
| 16 | +This applies to: Python, C++, Objective-C, Swift, Metal shaders, shell scripts, Makefiles, CMake files, configuration files that support comments, and benchmark scripts. | |
| 17 | + | |
| 18 | +#### Python / shell / YAML / TOML header | |
| 19 | + | |
| 20 | +```python | |
| 21 | +# ============================================================================= | |
| 22 | +# Project : localvm-research | |
| 23 | +# File : <relative/path/to/file.py> | |
| 24 | +# Purpose : <one-line description of what this file does> | |
| 25 | +# Author : Simon-Pierre Boucher | |
| 26 | +# Contact : contact@spboucher.ai | |
| 27 | +# Created : <YYYY-MM-DD> | |
| 28 | +# Modified : <YYYY-MM-DD> | |
| 29 | +# Platform : macOS / Apple Silicon (arm64) | |
| 30 | +# License : All rights reserved (research code) | |
| 31 | +# ============================================================================= | |
| 32 | +``` | |
| 33 | + | |
| 34 | +#### C++ / Metal / Swift / Objective-C header | |
| 35 | + | |
| 36 | +```cpp | |
| 37 | +// ============================================================================ | |
| 38 | +// Project : localvm-research | |
| 39 | +// File : <relative/path/to/file.cpp> | |
| 40 | +// Purpose : <one-line description> | |
| 41 | +// Author : Simon-Pierre Boucher | |
| 42 | +// Contact : contact@spboucher.ai | |
| 43 | +// Created : <YYYY-MM-DD> | |
| 44 | +// Modified : <YYYY-MM-DD> | |
| 45 | +// Platform : macOS / Apple Silicon (arm64) — Metal / Accelerate / MLX | |
| 46 | +// License : All rights reserved (research code) | |
| 47 | +// ============================================================================ | |
| 48 | +``` | |
| 49 | + | |
| 50 | +#### Markdown research documents header (front matter) | |
| 51 | + | |
| 52 | +```markdown | |
| 53 | +--- | |
| 54 | +project: localvm-research | |
| 55 | +document: <name> | |
| 56 | +author: Simon-Pierre Boucher | |
| 57 | +contact: contact@spboucher.ai | |
| 58 | +created: <YYYY-MM-DD> | |
| 59 | +status: draft | reviewed | final | |
| 60 | +--- | |
| 61 | +``` | |
| 62 | + | |
| 63 | +Rules: | |
| 64 | + | |
| 65 | +1. The header must be the **first content** of the file (after a shebang line if one exists). | |
| 66 | +2. `Modified` must be updated whenever the file is substantially changed. | |
| 67 | +3. A CI-style check script (`tools/check_headers.py`) must be written early in the project and run before every commit; it fails if any tracked source file lacks a conforming header. | |
| 68 | +4. Generated files (e.g., results JSON) are exempt, but the generator must embed `"author": "Simon-Pierre Boucher", "contact": "contact@spboucher.ai"` in output metadata where format permits. | |
| 69 | + | |
| 70 | +### 0.2 macOS-first design constraint | |
| 71 | + | |
| 72 | +**Everything in this project must be designed to run on a Mac.** Specifically: | |
| 73 | + | |
| 74 | +* Target machine class: Apple Silicon (M1/M2/M3/M4 family), 16–64 GB unified memory, internal NVMe SSD. | |
| 75 | +* Default compute paths: **MLX**, **Metal (MSL kernels)**, **Accelerate/BLAS**, **PyTorch with MPS backend**, plain CPU (arm64 NEON). | |
| 76 | +* CUDA is allowed **only** as an optional, clearly isolated validation path (`src/backends/cuda_optional/`), never a dependency of the core runtime. | |
| 77 | +* All I/O experiments must account for macOS specifics: APFS behavior, the unified page cache, `mmap` semantics on macOS, `F_NOCACHE`/`fcntl` instead of Linux `O_DIRECT`, `posix_fadvise` absence, `purge`/`vm_stat` for memory pressure measurement, and Apple SSD controller characteristics. | |
| 78 | +* Instrumentation must use macOS-native sources where possible: `task_info` / `mach` APIs, `vm_stat`, `fs_usage`, `powermetrics` (energy, requires sudo — degrade gracefully), Instruments traces where practical, `sysctl hw.*` for hardware discovery. | |
| 79 | +* Build tooling: `uv` or `pip` + `venv` for Python; `cmake` + AppleClang for C++; `xcrun -sdk macosx metal` for Metal shader compilation. No Linux-only assumptions anywhere in the core. | |
| 80 | +* A hardware manifest (`benchmarks/hardware_manifest.py`) must record chip model, core counts (P/E), GPU core count, memory size, SSD model, macOS version, and software versions into every result file. | |
| 81 | + | |
| 82 | +### 0.3 Repository discipline | |
| 83 | + | |
| 84 | +* Git from day one. Meaningful commits. No giant "misc" commits. | |
| 85 | +* Every experiment result must be reproducible from: (commit hash) + (config file) + (seed) + (hardware manifest). | |
| 86 | +* Python: type hints, `ruff` for lint/format, `pytest` for correctness tests of numerical code. | |
| 87 | +* C++: `-Wall -Wextra -Werror`, sanitizers in debug builds. | |
| 88 | +* No result may be reported from an uncommitted working tree. | |
| 89 | + | |
| 90 | +--- | |
| 91 | + | |
| 92 | +## 1. Mission | |
| 93 | + | |
| 94 | +Your objective is to investigate, design, implement, and experimentally validate a genuinely new way to run **existing pretrained open-weight large language models that normally do not fit comfortably in consumer-Mac memory** on ordinary local Apple Silicon hardware. | |
| 95 | + | |
| 96 | +The target problem is **not**: | |
| 97 | + | |
| 98 | +* training a new foundation model; | |
| 99 | +* designing a smaller replacement model; | |
| 100 | +* merely applying standard quantization; | |
| 101 | +* merely using CPU offload; | |
| 102 | +* merely using SSD swap; | |
| 103 | +* merely pruning a model once and accepting permanent quality loss; | |
| 104 | +* or reproducing llama.cpp, MLX, PowerInfer, FlexGen, speculative decoding, or another existing system. | |
| 105 | + | |
| 106 | +The target is broader and more ambitious: | |
| 107 | + | |
| 108 | +> **Given an already-trained model whose normal memory and bandwidth requirements exceed the target Mac, determine whether its execution can be reorganized, transformed, compiled, approximated, decomposed, scheduled, cached, paged, predicted, refined, or otherwise executed differently so that the model remains meaningfully useful on consumer Apple Silicon hardware with dramatically lower resident memory and/or memory bandwidth requirements.** | |
| 109 | + | |
| 110 | +Do not assume in advance what the solution should be. | |
| 111 | +Do not force a particular architecture. | |
| 112 | +Do not begin implementation before understanding the state of the art. | |
| 113 | +Your job is to discover what is actually possible. | |
| 114 | + | |
| 115 | +--- | |
| 116 | + | |
| 117 | +## 2. Core research question | |
| 118 | + | |
| 119 | +Investigate: | |
| 120 | + | |
| 121 | +> **Can an existing dense or MoE pretrained LLM be transformed post-training into an execution representation whose instantaneous working set is dramatically smaller than the full checkpoint, while preserving most or all of the original model's useful capabilities?** | |
| 122 | + | |
| 123 | +The most important distinction is: | |
| 124 | + | |
| 125 | +```text | |
| 126 | +total model size | |
| 127 | +≠ | |
| 128 | +resident model size | |
| 129 | +≠ | |
| 130 | +bytes read per token | |
| 131 | +≠ | |
| 132 | +parameters materially required for a particular token | |
| 133 | +``` | |
| 134 | + | |
| 135 | +Explore whether these quantities can be decoupled. | |
| 136 | + | |
| 137 | +A successful system could potentially make a model much larger than available unified memory usable locally on a Mac, where additional model size primarily increases latency or storage requirements rather than making execution impossible. | |
| 138 | + | |
| 139 | +### Guiding principle | |
| 140 | + | |
| 141 | +Do not optimize first for benchmark scores. Initially optimize for discovering whether there is a **new execution regime**. | |
| 142 | + | |
| 143 | +The main scientific question is: | |
| 144 | + | |
| 145 | +```text | |
| 146 | +How little of the original model must actually be represented, | |
| 147 | +loaded, reconstructed, or evaluated to reproduce its behavior? | |
| 148 | +``` | |
| 149 | + | |
| 150 | +Treat this as a systems + machine-learning research problem. You are free to discover that the initial premise is wrong. **Negative experimental results are useful.** | |
| 151 | + | |
| 152 | +--- | |
| 153 | + | |
| 154 | +## 3. Project structure (real research-project layout) | |
| 155 | + | |
| 156 | +The repository must follow this layout. Create the skeleton (with header-compliant placeholder files) before Phase 1 concludes. | |
| 157 | + | |
| 158 | +```text | |
| 159 | +localvm-research/ | |
| 160 | +├── CLAUDE.md # this charter | |
| 161 | +├── README.md # public-facing summary (written last, updated continuously) | |
| 162 | +├── CITATION.cff # citation metadata (author: Simon-Pierre Boucher) | |
| 163 | +├── LICENSE | |
| 164 | +├── pyproject.toml # Python project config (ruff, pytest, deps) | |
| 165 | +├── Makefile # top-level tasks: setup, lint, test, bench, headers | |
| 166 | +│ | |
| 167 | +├── research/ # the scientific paper trail | |
| 168 | +│ ├── LOG.md # dated research log (append-only) | |
| 169 | +│ ├── state_of_the_art.md # Phase 2 deliverable | |
| 170 | +│ ├── research_gaps.md # Phase 3 deliverable | |
| 171 | +│ ├── candidate_ranking.md # Phase 4 deliverable | |
| 172 | +│ ├── bibliography.md # every source, with links and access dates | |
| 173 | +│ ├── novelty_check.md # Phase 11 deliverable | |
| 174 | +│ └── notes/ # per-topic reading notes (one file per theme) | |
| 175 | +│ | |
| 176 | +├── src/ # core library code | |
| 177 | +│ ├── localvm/ | |
| 178 | +│ │ ├── __init__.py | |
| 179 | +│ │ ├── models/ # model loading, checkpoint parsing (safetensors/GGUF) | |
| 180 | +│ │ ├── transforms/ # quantization, decomposition, encodings | |
| 181 | +│ │ ├── runtime/ # paging, scheduling, caching, prediction | |
| 182 | +│ │ ├── backends/ | |
| 183 | +│ │ │ ├── mlx_backend/ # MLX / Metal primary path | |
| 184 | +│ │ │ ├── mps_backend/ # PyTorch-MPS path | |
| 185 | +│ │ │ ├── cpu_backend/ # Accelerate / NEON path | |
| 186 | +│ │ │ └── cuda_optional/ # isolated, optional | |
| 187 | +│ │ ├── instrumentation/ # macOS-native measurement (mach, vm_stat, fs_usage…) | |
| 188 | +│ │ └── quality/ # perplexity, KL, decision-stability metrics | |
| 189 | +│ └── kernels/ # custom Metal (.metal) and C++ kernels | |
| 190 | +│ | |
| 191 | +├── experiments/ # micro-experiments and candidate prototypes | |
| 192 | +│ ├── micro/ | |
| 193 | +│ │ ├── expA_weight_concentration/ | |
| 194 | +│ │ ├── expB_token_stability/ | |
| 195 | +│ │ ├── expC_semantic_locality/ | |
| 196 | +│ │ ├── expD_progressive_reconstruction/ | |
| 197 | +│ │ ├── expE_partial_gemm/ | |
| 198 | +│ │ ├── expF_error_accumulation/ | |
| 199 | +│ │ ├── expG_decision_stability/ | |
| 200 | +│ │ └── expH_ssd_feasibility/ | |
| 201 | +│ ├── candidate_01/ | |
| 202 | +│ ├── candidate_02/ | |
| 203 | +│ └── candidate_03/ | |
| 204 | +│ └── (each candidate contains:) | |
| 205 | +│ ├── README.md | |
| 206 | +│ ├── hypothesis.md | |
| 207 | +│ ├── implementation/ | |
| 208 | +│ ├── benchmark.py | |
| 209 | +│ ├── results/ | |
| 210 | +│ └── analysis.md | |
| 211 | +│ | |
| 212 | +├── benchmarks/ # baselines and standardized harness | |
| 213 | +│ ├── harness.py # unified benchmark runner | |
| 214 | +│ ├── hardware_manifest.py # macOS hardware/software fingerprinting | |
| 215 | +│ ├── baselines/ # llama.cpp, MLX, mmap, offload configs | |
| 216 | +│ └── datasets/ # eval prompts: code, math, chat, FR, EN, reasoning | |
| 217 | +│ | |
| 218 | +├── results/ # raw + aggregated results (JSON/CSV + plots) | |
| 219 | +│ └── <experiment_id>/<timestamp>/ | |
| 220 | +│ | |
| 221 | +├── tools/ | |
| 222 | +│ ├── check_headers.py # enforces §0.1 | |
| 223 | +│ ├── new_experiment.py # scaffolds a compliant experiment directory | |
| 224 | +│ └── report.py # generates result tables/plots | |
| 225 | +│ | |
| 226 | +└── docs/ # architecture docs, diagrams, final writeups | |
| 227 | +``` | |
| 228 | + | |
| 229 | +Every experiment directory is scaffolded by `tools/new_experiment.py`, which auto-inserts the author header and a `hypothesis.md` template containing the seven-field scientific-discipline block (§10). | |
| 230 | + | |
| 231 | +--- | |
| 232 | + | |
| 233 | +## 4. Phase 1 — Ultra-deep web and literature research | |
| 234 | + | |
| 235 | +Before proposing an architecture, perform an extremely deep search of current literature, repositories, technical reports, conference papers, preprints, blog posts, implementations, issue discussions, benchmarks, and systems research. | |
| 236 | + | |
| 237 | +The search must be current. Search broadly and recursively. Do not stop after finding several obvious papers. Follow citations backward and forward whenever useful. | |
| 238 | + | |
| 239 | +Search arXiv, OpenReview, conference proceedings (MLSys, OSDI, SOSP, ASPLOS, ISCA, NeurIPS, ICML, ICLR, ACL), GitHub, Hugging Face, systems research venues, vendor engineering documentation (especially **Apple ML/Metal engineering material and MLX repos**), academic project pages, and relevant technical discussions. | |
| 240 | + | |
| 241 | +Prefer primary sources. For every important technique, find the actual paper and, whenever available, the implementation. Log every consulted source in `research/bibliography.md` with URL and access date. | |
| 242 | + | |
| 243 | +### Areas that must be investigated | |
| 244 | + | |
| 245 | +At minimum investigate all of the following, while remaining open to unrelated approaches. | |
| 246 | + | |
| 247 | +#### 4.1 Quantization | |
| 248 | + | |
| 249 | +PTQ; QAT; 8-bit; 6-bit; 4-bit; 3-bit; 2-bit; 1.58-bit; ternary weights; 1-bit approaches; mixed precision; per-layer precision; per-channel precision; per-token precision; dynamic precision; progressive precision; residual quantization; recurrent residual quantization; additive quantization; vector quantization; lattice quantization; codebook methods; weight-only quantization; activation quantization; KV-cache quantization; extreme low-bit inference. | |
| 250 | + | |
| 251 | +Study quality degradation and actual memory-bandwidth effects **separately**. Pay particular attention to which formats have efficient Metal/MLX kernels versus which exist only on CUDA. | |
| 252 | + | |
| 253 | +#### 4.2 Activation sparsity | |
| 254 | + | |
| 255 | +Contextual sparsity; dynamic activation sparsity; FFN sparsity; neuron activation prediction; top-k neuron selection; ReLUfication; SwiGLU sparsification; structured sparsity; unstructured sparsity; N:M sparsity; activation predictors; learned sparsity routers; post-training induced sparsity. | |
| 256 | + | |
| 257 | +Study systems including but not limited to: DejaVu; ShadowLLM; PowerInfer; PowerInfer-2; DynamicInfer; SparQ; contextual sparsity systems. Determine exactly what is already known, and what portions assume discrete-GPU architectures that do not map to unified memory. | |
| 258 | + | |
| 259 | +#### 4.3 Weight sparsity and pruning | |
| 260 | + | |
| 261 | +SparseGPT; Wanda; magnitude pruning; structured pruning; block pruning; channel pruning; layer dropping; width pruning; depth pruning; one-shot pruning; dynamic pruning; recoverable pruning; reversible pruning; conditional pruning. | |
| 262 | + | |
| 263 | +Ask whether discarded weights could instead live on the Mac's NVMe SSD and be recovered only when needed. | |
| 264 | + | |
| 265 | +#### 4.4 Out-of-core inference | |
| 266 | + | |
| 267 | +CPU/GPU offload; RAM/VRAM tiering; NVMe offload; mmap; asynchronous I/O; direct I/O; page cache behavior; pinned memory; unified memory; **Apple Silicon memory behavior specifically**; GPU prefetch; tensor paging; weight streaming; SSD-to-GPU pipelines; near-storage inference; computational storage. | |
| 268 | + | |
| 269 | +Investigate systems such as: FlexGen; DeepSpeed inference; ZeRO-Inference; llama.cpp; MLX; PowerInfer; M2Cache; SolidAttention; Petals where relevant; distributed consumer inference systems. | |
| 270 | + | |
| 271 | +Measure whether the true bottleneck is capacity, bandwidth, latency, random I/O, or synchronization — **on macOS/APFS/Apple NVMe, not on Linux assumptions**. | |
| 272 | + | |
| 273 | +#### 4.5 Model decomposition | |
| 274 | + | |
| 275 | +Research whether pretrained weights can be represented as `base + residual`, `shared component + layer-specific correction`, or `low-rank component + sparse residual`. | |
| 276 | + | |
| 277 | +Investigate: SVD; truncated SVD; tensor decomposition; low-rank factorization; LoRA-like decomposition of existing weights; cross-layer sharing; DeltaLLM; matrix dictionaries; learned codebooks; basis decomposition; Kronecker decomposition; tensor trains; product quantization; weight clustering; block-level factorization; shared latent weight representations. | |
| 278 | + | |
| 279 | +Determine whether model layers contain exploitable redundancy that existing runtimes ignore. | |
| 280 | + | |
| 281 | +#### 4.6 Progressive and approximate computation | |
| 282 | + | |
| 283 | +Progressive inference; anytime neural networks; early exit; adaptive computation; dynamic depth; conditional computation; residual refinement; coarse-to-fine inference; iterative refinement; approximate matrix multiplication; error-bounded GEMM; approximate computing; lazy tensor evaluation; partial matrix multiplication; adaptive precision numerical computing. | |
| 284 | + | |
| 285 | +Do not limit this search to LLM research. Look at computer architecture, numerical linear algebra, databases, graphics, signal processing, scientific computing, and HPC. Potentially useful concepts may already exist outside machine learning. | |
| 286 | + | |
| 287 | +#### 4.7 Speculative execution | |
| 288 | + | |
| 289 | +Speculative decoding; self-speculative decoding; draft models; Medusa-like approaches; verification methods; exact distribution preservation; optimistic execution; rollback; branch prediction; confidence-based speculative computation. | |
| 290 | + | |
| 291 | +Ask whether speculation can happen **inside a transformer forward pass**, not only across future tokens. | |
| 292 | + | |
| 293 | +#### 4.8 Memory systems (outside AI literature) | |
| 294 | + | |
| 295 | +Virtual memory; demand paging; working-set theory; page replacement; TLBs; cache associativity; hardware prefetchers; branch predictors; speculative execution; NUMA; memory compression (including **macOS compressed memory**); compressed caches; tiered memory; CXL memory; object stores; database buffer pools; columnar execution; query optimizers. | |
| 296 | + | |
| 297 | +Ask: *What ideas from operating systems and CPU architecture have never been properly translated to neural-weight execution?* | |
| 298 | + | |
| 299 | +#### 4.9 Numerical error analysis | |
| 300 | + | |
| 301 | +Interval arithmetic; affine arithmetic; probabilistic bounds; matrix norm bounds; perturbation theory; Lipschitz bounds; error propagation; certified neural networks; robustness certification; approximate linear algebra; bounds for quantized networks. | |
| 302 | + | |
| 303 | +A potentially important direction: can computation terminate when additional accuracy can no longer meaningfully affect the output? Do not assume this is feasible. Test it. | |
| 304 | + | |
| 305 | +#### 4.10 Output-decision stability | |
| 306 | + | |
| 307 | +Investigate the distinction between *reproducing exact hidden states* and *producing the same useful output*. | |
| 308 | + | |
| 309 | +For greedy decoding, investigate whether a token decision can be certified without fully reconstructing every upstream operation. For sampling, investigate whether approximate intermediate computation can still preserve or closely approximate the original probability distribution. | |
| 310 | + | |
| 311 | +Explore: top-1 logit margins; top-k stability; KL divergence; total variation distance; distributional guarantees; acceptance/rejection correction; speculative verification. | |
| 312 | + | |
| 313 | +This is an important area but is **not prescribed as the final approach**. | |
| 314 | + | |
| 315 | +--- | |
| 316 | + | |
| 317 | +## 5. Phase 2 — State-of-the-art map | |
| 318 | + | |
| 319 | +Produce `research/state_of_the_art.md` (with the §0.1 front-matter header). | |
| 320 | + | |
| 321 | +It must organize every relevant technique by: | |
| 322 | + | |
| 323 | +```text | |
| 324 | +Technique | |
| 325 | +Problem addressed | |
| 326 | +Model modification required? | |
| 327 | +Retraining required? | |
| 328 | +Memory reduction | |
| 329 | +Bandwidth reduction | |
| 330 | +Compute reduction | |
| 331 | +Latency effect | |
| 332 | +Quality degradation | |
| 333 | +Hardware assumptions (explicitly: does it work on Apple Silicon / Metal?) | |
| 334 | +Open-source implementation (and whether it builds on macOS arm64) | |
| 335 | +Main limitation | |
| 336 | +Opportunity for extension | |
| 337 | +``` | |
| 338 | + | |
| 339 | +Do not simply summarize papers. Identify where approaches overlap. Identify combinations that have already been tried. Identify ideas that initially seem novel but are actually already known. | |
| 340 | + | |
| 341 | +--- | |
| 342 | + | |
| 343 | +## 6. Phase 3 — Identify genuine gaps | |
| 344 | + | |
| 345 | +Produce `research/research_gaps.md`. | |
| 346 | + | |
| 347 | +For every promising gap explain: | |
| 348 | + | |
| 349 | +1. what existing systems do; | |
| 350 | +2. what they do not do; | |
| 351 | +3. why the missing capability might matter; | |
| 352 | +4. whether there is a plausible mathematical or systems reason it could work; | |
| 353 | +5. the biggest reason it might fail; | |
| 354 | +6. the smallest experiment capable of falsifying it — **runnable on a Mac**. | |
| 355 | + | |
| 356 | +Generate many candidate ideas. Aim for at least **20 substantially different approaches**. Do not make them superficial variants of the same idea. | |
| 357 | + | |
| 358 | +Example categories (non-binding): execution reordering; learned weight paging; progressive reconstruction; activation-conditioned decompression; semantic caches; low-rank hot path + residual cold path; predictive SSD reads; dynamic precision; partial GEMM; temporary model specialization; token-dependent model materialization; model-state compression; weight synthesis; cross-layer reuse; hidden-state approximation; error-controlled execution; reversible approximation; adaptive layer reconstruction. | |
| 359 | + | |
| 360 | +These are examples only. Do not constrain the search to them. | |
| 361 | + | |
| 362 | +--- | |
| 363 | + | |
| 364 | +## 7. Phase 4 — Rank candidate approaches | |
| 365 | + | |
| 366 | +Create `research/candidate_ranking.md`. | |
| 367 | + | |
| 368 | +Score every idea 1–10, with written reasoning, on: | |
| 369 | + | |
| 370 | +```text | |
| 371 | +Novelty | |
| 372 | +Technical plausibility | |
| 373 | +Expected memory reduction | |
| 374 | +Expected bandwidth reduction | |
| 375 | +Expected quality retention | |
| 376 | +Implementation complexity | |
| 377 | +Hardware practicality on Apple Silicon (Metal/MLX kernel feasibility, unified memory fit) | |
| 378 | +Post-training compatibility | |
| 379 | +Potential research significance | |
| 380 | +Risk | |
| 381 | +``` | |
| 382 | + | |
| 383 | +Select roughly **3–5 strongest candidates** for experiments. | |
| 384 | + | |
| 385 | +Prefer ideas that could fundamentally change the scaling relationship between `model size` and `required resident memory / bytes transferred per token`. | |
| 386 | + | |
| 387 | +--- | |
| 388 | + | |
| 389 | +## 8. Phase 5 — Experimental framework | |
| 390 | + | |
| 391 | +Build an experimental framework **before** attempting large models. The system must make experiments reproducible. | |
| 392 | + | |
| 393 | +Preferred languages and stacks (Mac-first): | |
| 394 | + | |
| 395 | +```text | |
| 396 | +Python (MLX, PyTorch-MPS, NumPy) for research tooling | |
| 397 | +C++ (AppleClang, Accelerate) where low-level control matters | |
| 398 | +Metal Shading Language for custom Apple GPU kernels | |
| 399 | +Swift/Objective-C shims only where mach/IOKit APIs require them | |
| 400 | +CUDA only as isolated optional validation on non-Mac hardware | |
| 401 | +``` | |
| 402 | + | |
| 403 | +Do not prematurely optimize. Correctness and measurement come first. | |
| 404 | + | |
| 405 | +### 8.1 Initial model sizes | |
| 406 | + | |
| 407 | +Start small. Use models in approximately this progression: | |
| 408 | + | |
| 409 | +```text | |
| 410 | +0.5B–1B → 3B → 7B–8B → 14B → 32B | |
| 411 | +``` | |
| 412 | + | |
| 413 | +Only move to 70B+ if evidence supports it. Prefer modern open-weight architectures representative of models we ultimately want to run, with checkpoints available in safetensors and GGUF. | |
| 414 | + | |
| 415 | +### 8.2 Instrumentation (macOS-native) | |
| 416 | + | |
| 417 | +The framework must measure, when applicable: | |
| 418 | + | |
| 419 | +```text | |
| 420 | +resident RAM (mach task_info) peak RAM | |
| 421 | +mapped memory GPU/unified memory in use | |
| 422 | +SSD reads (fs_usage / iostat) SSD bytes/token | |
| 423 | +RAM bytes/token effective weight bytes/token | |
| 424 | +tokens/second time-to-first-token | |
| 425 | +per-token latency CPU utilization (P vs E cores) | |
| 426 | +GPU utilization SSD utilization | |
| 427 | +energy via powermetrics (if sudo) cache hit rate | |
| 428 | +page faults (vm_stat deltas) number of parameters touched | |
| 429 | +number of blocks touched effective precision used | |
| 430 | +recomputation count prediction hit rate | |
| 431 | +memory-pressure / compressor activity thermal state (throttling detection) | |
| 432 | +``` | |
| 433 | + | |
| 434 | +Also measure quality: | |
| 435 | + | |
| 436 | +```text | |
| 437 | +perplexity logit correlation | |
| 438 | +KL divergence same greedy token rate | |
| 439 | +top-k overlap task benchmark accuracy | |
| 440 | +generation similarity long-context behavior | |
| 441 | +coding behavior reasoning behavior | |
| 442 | +``` | |
| 443 | + | |
| 444 | +### 8.3 Most important systems metric | |
| 445 | + | |
| 446 | +Track **BYTES READ PER GENERATED TOKEN** separately from model size. | |
| 447 | +Also track **ACTIVE / TOUCHED PARAMETERS PER TOKEN** where meaningful. | |
| 448 | + | |
| 449 | +A system that stores a 150 GB checkpoint but reads only 5 GB per generated token may be much more interesting than one that compresses the checkpoint to 70 GB but reads all 70 GB every token. | |
| 450 | + | |
| 451 | +### 8.4 Baselines | |
| 452 | + | |
| 453 | +At minimum compare against appropriate configurations of: | |
| 454 | + | |
| 455 | +```text | |
| 456 | +full precision where practical | |
| 457 | +Q8 / Q6 / Q5 / Q4 / Q3 / Q2 (where practical) | |
| 458 | +llama.cpp (Metal build) | |
| 459 | +MLX (native) | |
| 460 | +CPU offloading | |
| 461 | +mmap streaming | |
| 462 | +standard SSD offloading | |
| 463 | +``` | |
| 464 | + | |
| 465 | +Also reproduce relevant published methods when feasible. Do not claim improvement against straw-man baselines. | |
| 466 | + | |
| 467 | +--- | |
| 468 | + | |
| 469 | +## 9. Phase 6 — Micro-experiments | |
| 470 | + | |
| 471 | +Before implementing a large runtime, answer fundamental questions empirically. Each lives in `experiments/micro/` with the standard scaffold. | |
| 472 | + | |
| 473 | +### Experiment A — Weight contribution concentration | |
| 474 | +For each transformer layer and token, measure how much of the output norm arises from subsets of weight blocks. Ask: can 10%, 20%, 40%, or 60% of blocks reproduce most of the layer output? Test across: code, math, chat, French, English, reasoning, random text, long context. | |
| 475 | + | |
| 476 | +### Experiment B — Stability across consecutive tokens | |
| 477 | +Measure overlap between important blocks at tokens t, t+1, t+2. Compute Jaccard similarity, transition probabilities, working-set lifetime. Determine whether weight access is predictable. | |
| 478 | + | |
| 479 | +### Experiment C — Cross-prompt semantic locality | |
| 480 | +Ask whether prompts belonging to the same semantic domain repeatedly rely on similar regions. If so, investigate whether domain-specific weight caches are possible. | |
| 481 | + | |
| 482 | +### Experiment D — Progressive weight reconstruction | |
| 483 | +Represent weights using multiple progressive approximations (2-bit only; 2+residual; 2+2 residuals; …). For each token/layer determine how rapidly hidden-state error, logit error, and the token decision converge. | |
| 484 | + | |
| 485 | +### Experiment E — Partial matrix multiplication | |
| 486 | +Compute only selected weight blocks. Measure quality vs blocks evaluated. Then determine whether important blocks can be predicted cheaply. Implement at least one Metal kernel variant to check that block-skipping actually saves bandwidth on Apple GPUs (not just FLOPs on paper). | |
| 487 | + | |
| 488 | +### Experiment F — Error accumulation | |
| 489 | +Introduce controlled approximation at individual layers. Determine which layers tolerate error, which amplify error, which recover from error. Map model sensitivity. | |
| 490 | + | |
| 491 | +### Experiment G — Decision stability | |
| 492 | +For an approximate forward pass, compare top logits against the exact model. Ask whether many token decisions become stable before full model precision is available. | |
| 493 | + | |
| 494 | +### Experiment H — SSD feasibility (macOS-specific) | |
| 495 | +Simulate realistic storage on the actual Mac's internal NVMe. Do NOT rely on theoretical bandwidth. Measure actual random and sequential reads at 4 KB, 16 KB, 64 KB, 256 KB, 1 MB, 4 MB — with and without page cache (`F_NOCACHE`), cold vs warm APFS state. Measure concurrent reads while Metal GPU compute occurs. Test whether useful prefetch overlap exists. Record SSD model and thermal state; Apple SSDs throttle. | |
| 496 | + | |
| 497 | +--- | |
| 498 | + | |
| 499 | +## 10. Scientific discipline | |
| 500 | + | |
| 501 | +For every experiment explicitly write, in its `hypothesis.md` / `analysis.md`: | |
| 502 | + | |
| 503 | +```text | |
| 504 | +Hypothesis | |
| 505 | +Falsification criterion | |
| 506 | +Method | |
| 507 | +Baseline | |
| 508 | +Result | |
| 509 | +Interpretation | |
| 510 | +Next experiment | |
| 511 | +``` | |
| 512 | + | |
| 513 | +Avoid confirmation bias. If an idea fails, record why. **Do not silently discard failures.** | |
| 514 | + | |
| 515 | +### Evidence standard | |
| 516 | + | |
| 517 | +Never write "this is faster / novel / better / should scale" without evidence. Use benchmark numbers. Whenever possible report: | |
| 518 | + | |
| 519 | +```text | |
| 520 | +mean, median, standard deviation, number of runs, | |
| 521 | +hardware (chip, RAM, SSD, macOS version), model, context length, | |
| 522 | +generation length, quantization, software versions (MLX, PyTorch, Metal), | |
| 523 | +thermal conditions | |
| 524 | +``` | |
| 525 | + | |
| 526 | +--- | |
| 527 | + | |
| 528 | +## 11. Phase 7 — Prototype candidate architectures | |
| 529 | + | |
| 530 | +For each of the strongest ideas create its own directory: | |
| 531 | + | |
| 532 | +```text | |
| 533 | +experiments/candidate_01/ | |
| 534 | +experiments/candidate_02/ | |
| 535 | +experiments/candidate_03/ | |
| 536 | +``` | |
| 537 | + | |
| 538 | +Each candidate must include: | |
| 539 | + | |
| 540 | +```text | |
| 541 | +README.md hypothesis.md | |
| 542 | +implementation/ benchmark.py | |
| 543 | +results/ analysis.md | |
| 544 | +``` | |
| 545 | + | |
| 546 | +All implementation files carry the §0.1 header and must run on the primary Mac target without CUDA. | |
| 547 | + | |
| 548 | +--- | |
| 549 | + | |
| 550 | +## 12. Phase 8 — Automatic research loop | |
| 551 | + | |
| 552 | +Operate as a research agent. After every experiment: | |
| 553 | + | |
| 554 | +1. analyze results; | |
| 555 | +2. determine the most informative next experiment; | |
| 556 | +3. search the literature again if results reveal something unexpected; | |
| 557 | +4. update hypotheses; | |
| 558 | +5. modify the candidate architecture; | |
| 559 | +6. rerun; | |
| 560 | +7. compare; | |
| 561 | +8. continue until evidence strongly favors or rejects the approach. | |
| 562 | + | |
| 563 | +Do not follow a rigid predefined implementation roadmap if experiments contradict it. | |
| 564 | + | |
| 565 | +### Research log | |
| 566 | + | |
| 567 | +Maintain `research/LOG.md` (append-only). Every substantial action must contain: | |
| 568 | + | |
| 569 | +```text | |
| 570 | +date/time (local, with timezone) | |
| 571 | +question | |
| 572 | +experiment | |
| 573 | +result | |
| 574 | +interpretation | |
| 575 | +decision | |
| 576 | +``` | |
| 577 | + | |
| 578 | +This must make the entire reasoning process auditable. | |
| 579 | + | |
| 580 | +--- | |
| 581 | + | |
| 582 | +## 13. Phase 9 — Try to discover a new execution abstraction | |
| 583 | + | |
| 584 | +Do not merely seek an optimization. Seek an abstraction that could change how large local models are executed. Useful questions include: | |
| 585 | + | |
| 586 | +```text | |
| 587 | +Could model weights behave like virtual memory? | |
| 588 | +Could only a token-specific working set be materialized? | |
| 589 | +Could a model be represented as a cheap approximate core plus recoverable information? | |
| 590 | +Could computation proceed before all weights are available? | |
| 591 | +Could missing computation be added later only when needed? | |
| 592 | +Could weights be reconstructed from shared bases? | |
| 593 | +Could hidden-state trajectories predict future memory accesses? | |
| 594 | +Could the system learn its own cache policy? | |
| 595 | +Could model execution become demand-driven? | |
| 596 | +Could the runtime optimize for decision stability rather than numerical exactness? | |
| 597 | +Could a model larger than RAM become usable because RAM limits working-set size | |
| 598 | +rather than total model size? | |
| 599 | +Could Apple's unified memory + fast NVMe make an abstraction viable that | |
| 600 | +discrete-GPU architectures cannot support? | |
| 601 | +``` | |
| 602 | + | |
| 603 | +These are research questions, not required design decisions. | |
| 604 | + | |
| 605 | +--- | |
| 606 | + | |
| 607 | +## 14. Phase 10 — Build the best prototype supported by evidence | |
| 608 | + | |
| 609 | +Once experiments clearly favor an architecture, build a prototype runtime. A possible CLI shape could eventually be: | |
| 610 | + | |
| 611 | +```bash | |
| 612 | +localvm compile MODEL_PATH \ | |
| 613 | + --target-memory 16GB \ | |
| 614 | + --storage /Volumes/FastNVMe/localvm | |
| 615 | +``` | |
| 616 | + | |
| 617 | +then: | |
| 618 | + | |
| 619 | +```bash | |
| 620 | +localvm run COMPILED_MODEL | |
| 621 | +``` | |
| 622 | + | |
| 623 | +Naming and architecture should only be finalized after research. | |
| 624 | + | |
| 625 | +### Compilation stage | |
| 626 | + | |
| 627 | +If useful, compilation may perform offline operations such as: profiling; weight analysis; quantization; factorization; clustering; reordering; block creation; index construction; activation tracing; cache-profile creation; predictor training; error-bound estimation; progressive encoding; layout optimization (aligned to APFS/Metal buffer constraints). | |
| 628 | + | |
| 629 | +Compilation can take substantial time. Inference must be the optimized stage. | |
| 630 | + | |
| 631 | +### Hard constraint | |
| 632 | + | |
| 633 | +The original pretrained model must remain the source model. You may transform its representation post-training. Small auxiliary predictors, indexes, adapters, or calibration passes are allowed if justified. **Do not solve the problem by simply training a new smaller LLM to replace it.** | |
| 634 | + | |
| 635 | +--- | |
| 636 | + | |
| 637 | +## 15. Target hardware | |
| 638 | + | |
| 639 | +Primary research target: | |
| 640 | + | |
| 641 | +```text | |
| 642 | +Apple Silicon Mac (laptop or desktop) | |
| 643 | +16–64 GB unified memory | |
| 644 | +internal Apple NVMe SSD (2–8 GB/s class) | |
| 645 | +Metal-capable GPU sharing memory with CPU | |
| 646 | +``` | |
| 647 | + | |
| 648 | +Apple Silicon is the primary platform because: | |
| 649 | + | |
| 650 | +```text | |
| 651 | +CPU and GPU share unified memory | |
| 652 | +Metal allows custom kernels | |
| 653 | +fast internal SSDs are standard | |
| 654 | +large memory configurations exist (up to 128–192 GB on desktop parts) | |
| 655 | +memory compression is built into the OS | |
| 656 | +``` | |
| 657 | + | |
| 658 | +The architecture should nevertheless remain conceptually hardware-independent; document (do not implement, unless trivial) how each mechanism would map to x86 + discrete GPU. | |
| 659 | + | |
| 660 | +### Stretch target | |
| 661 | + | |
| 662 | +```text | |
| 663 | +model total representation: 100–250+ GB | |
| 664 | +machine unified memory: 16–32 GB | |
| 665 | +useful generation speed: interactive or near-interactive | |
| 666 | +quality: close to original model | |
| 667 | +``` | |
| 668 | + | |
| 669 | +Do not assume this target is achievable. The research must establish the actual limits. | |
| 670 | + | |
| 671 | +--- | |
| 672 | + | |
| 673 | +## 16. What counts as a breakthrough | |
| 674 | + | |
| 675 | +A result is scientifically interesting if at least one of the following is demonstrated: | |
| 676 | + | |
| 677 | +**A.** A model significantly larger than unified memory runs locally on a Mac with acceptable interactive latency. | |
| 678 | +**B.** Bytes transferred per token become substantially smaller than the compressed checkpoint size. | |
| 679 | +**C.** Only a small token-dependent fraction of model information is required during typical inference. | |
| 680 | +**D.** A progressive or conditional execution mechanism preserves model quality while avoiding large amounts of weight loading. | |
| 681 | +**E.** A new post-training representation creates a qualitatively better storage/RAM/quality tradeoff than fixed quantization. | |
| 682 | +**F.** A new caching, prediction, scheduling, decomposition, or reconstruction mechanism materially changes out-of-core inference economics. | |
| 683 | + | |
| 684 | +## 17. Failure criteria | |
| 685 | + | |
| 686 | +Be willing to conclude that an approach does not work. For example: | |
| 687 | + | |
| 688 | +```text | |
| 689 | +SSD bandwidth fundamentally dominates | |
| 690 | +weight accesses are insufficiently predictable | |
| 691 | +required working set is nearly the entire model | |
| 692 | +approximation errors compound uncontrollably | |
| 693 | +low-bit base models destroy routing information | |
| 694 | +prediction overhead exceeds savings | |
| 695 | +random I/O eliminates theoretical advantages | |
| 696 | +quality degradation is unacceptable | |
| 697 | +macOS I/O or Metal dispatch overhead erases theoretical wins | |
| 698 | +``` | |
| 699 | + | |
| 700 | +If these occur, document them in `research/LOG.md` and the relevant `analysis.md`, then pivot. | |
| 701 | + | |
| 702 | +--- | |
| 703 | + | |
| 704 | +## 18. Deliverables | |
| 705 | + | |
| 706 | +Eventually produce (all with compliant headers): | |
| 707 | + | |
| 708 | +```text | |
| 709 | +README.md | |
| 710 | +CITATION.cff | |
| 711 | +research/ | |
| 712 | + state_of_the_art.md | |
| 713 | + research_gaps.md | |
| 714 | + candidate_ranking.md | |
| 715 | + novelty_check.md | |
| 716 | + LOG.md | |
| 717 | + bibliography.md | |
| 718 | +src/ | |
| 719 | +experiments/ | |
| 720 | +benchmarks/ | |
| 721 | +results/ | |
| 722 | +docs/ | |
| 723 | +tools/ | |
| 724 | +``` | |
| 725 | + | |
| 726 | +The final README must explain: | |
| 727 | + | |
| 728 | +```text | |
| 729 | +the problem | |
| 730 | +what existing systems do | |
| 731 | +what gap was discovered | |
| 732 | +the proposed architecture | |
| 733 | +why it should work | |
| 734 | +experimental evidence (with numbers, on named Mac hardware) | |
| 735 | +performance | |
| 736 | +limitations | |
| 737 | +how to reproduce (exact Mac setup instructions) | |
| 738 | +future research | |
| 739 | +``` | |
| 740 | + | |
| 741 | +--- | |
| 742 | + | |
| 743 | +## 19. Phase 11 — Novelty verification | |
| 744 | + | |
| 745 | +Before claiming novelty, perform a dedicated final literature search using terminology derived from the architecture actually discovered. Search for conceptual equivalents, not merely identical terminology. | |
| 746 | + | |
| 747 | +For example, if the architecture resembles `lazy neural execution`, `progressive weight materialization`, `conditional tensor paging`, or `activation-conditioned decompression` — search every plausible synonym. | |
| 748 | + | |
| 749 | +Assume an idea is **not** novel until evidence suggests otherwise. Record the process and conclusion in `research/novelty_check.md`. | |
| 750 | + | |
| 751 | +--- | |
| 752 | + | |
| 753 | +## 20. Most important instruction | |
| 754 | + | |
| 755 | +Do not become attached to any particular solution suggested in this document. | |
| 756 | + | |
| 757 | +The purpose of this project is **not to implement a preconceived WeightVM, NeuralOS, progressive quantizer, sparse runtime, or paging engine**. Those ideas are merely clues. | |
| 758 | + | |
| 759 | +The actual assignment is: | |
| 760 | + | |
| 761 | +> **Search deeply enough, reason independently enough, and experiment aggressively enough to discover the best technically plausible way of making an existing large pretrained model usable on a Mac that normally should not be able to run it.** | |
| 762 | + | |
| 763 | +Start with literature. Then generate hypotheses. Then falsify them experimentally. Let evidence determine the architecture. | |
| 764 | + | |
| 765 | +The ideal outcome is not simply another optimization. The ideal outcome is a mechanism that changes the relationship: | |
| 766 | + | |
| 767 | +```text | |
| 768 | +model size → hardware required | |
| 769 | +``` | |
| 770 | + | |
| 771 | +into something closer to: | |
| 772 | + | |
| 773 | +```text | |
| 774 | +instantaneous useful working set → hardware required | |
| 775 | +``` | |
| 776 | + | |
| 777 | +while keeping the intelligence already present in the original pretrained model. | |
| 778 | + | |
| 779 | +--- | |
| 780 | + | |
| 781 | +*Author: Simon-Pierre Boucher — contact@spboucher.ai — All research artifacts in this repository carry this attribution.* | |
added
LICENSE
+7 −0
@@ -0,0 +1,7 @@ | ||
| 1 | +Copyright (c) 2026 Simon-Pierre Boucher <contact@spboucher.ai> | |
| 2 | + | |
| 3 | +All rights reserved (research code). | |
| 4 | + | |
| 5 | +This repository contains research code and documents. No permission is granted | |
| 6 | +to use, copy, modify, or distribute this work, in whole or in part, without | |
| 7 | +prior written authorization from the author. | |
added
Makefile
+35 −0
@@ -0,0 +1,35 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : Makefile | |
| 4 | +# Purpose : Top-level tasks: setup, lint, test, bench, headers | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +PYTHON ?= python3 | |
| 14 | + | |
| 15 | +.PHONY: setup lint test bench headers manifest | |
| 16 | + | |
| 17 | +setup: | |
| 18 | + $(PYTHON) -m venv .venv | |
| 19 | + .venv/bin/pip install -e ".[dev,ml]" | |
| 20 | + | |
| 21 | +lint: | |
| 22 | + .venv/bin/ruff check src tools benchmarks experiments | |
| 23 | + .venv/bin/ruff format --check src tools benchmarks experiments | |
| 24 | + | |
| 25 | +test: | |
| 26 | + .venv/bin/pytest -q | |
| 27 | + | |
| 28 | +headers: | |
| 29 | + $(PYTHON) tools/check_headers.py | |
| 30 | + | |
| 31 | +manifest: | |
| 32 | + $(PYTHON) benchmarks/hardware_manifest.py | |
| 33 | + | |
| 34 | +bench: | |
| 35 | + @echo "benchmarks/harness.py not yet implemented (Phase 5)"; exit 1 | |
added
README.md
+44 −0
@@ -0,0 +1,44 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# localvm-research | |
| 11 | + | |
| 12 | +**Can an existing pretrained LLM that does not fit in a consumer Mac's memory be | |
| 13 | +transformed post-training into an execution representation whose instantaneous | |
| 14 | +working set is dramatically smaller than the full checkpoint — while preserving | |
| 15 | +most of its useful capabilities?** | |
| 16 | + | |
| 17 | +This repository is a living research project (charter: [CLAUDE.md](CLAUDE.md)). | |
| 18 | +The central distinction under investigation: | |
| 19 | + | |
| 20 | +```text | |
| 21 | +total model size ≠ resident model size ≠ bytes read per token ≠ parameters required for this token | |
| 22 | +``` | |
| 23 | + | |
| 24 | +- **Author:** Simon-Pierre Boucher — <contact@spboucher.ai> | |
| 25 | +- **Primary platform:** Apple Silicon Mac (unified memory, Metal, internal NVMe), macOS 14+ | |
| 26 | +- **Status:** Phase 1 (literature research) in progress. See `research/LOG.md` for the audit trail. | |
| 27 | + | |
| 28 | +## Layout | |
| 29 | + | |
| 30 | +| Path | Contents | | |
| 31 | +|---|---| | |
| 32 | +| `research/` | Scientific paper trail: log, state of the art, gaps, rankings, bibliography | | |
| 33 | +| `src/localvm/` | Core library (models, transforms, runtime, backends, instrumentation, quality) | | |
| 34 | +| `experiments/` | Micro-experiments (A–H) and candidate prototypes | | |
| 35 | +| `benchmarks/` | Unified harness, hardware manifest, baselines, eval datasets | | |
| 36 | +| `results/` | Raw + aggregated results (reproducible from commit + config + seed + manifest) | | |
| 37 | +| `tools/` | `check_headers.py`, `new_experiment.py`, `report.py` | | |
| 38 | + | |
| 39 | +## Reproducibility | |
| 40 | + | |
| 41 | +Every result is reproducible from: commit hash + config + seed + hardware manifest | |
| 42 | +(`benchmarks/hardware_manifest.py`). No result is reported from an uncommitted tree. | |
| 43 | + | |
| 44 | +*This README is updated continuously and finalized last (charter §18).* | |
added
benchmarks/baselines/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: benchmarks/baselines/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# benchmarks/baselines | |
| 11 | + | |
| 12 | +Baseline configurations: llama.cpp (Metal), MLX native, mmap streaming, offload. | |
added
benchmarks/datasets/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: benchmarks/datasets/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# benchmarks/datasets | |
| 11 | + | |
| 12 | +Eval prompt sets: code, math, chat, FR, EN, reasoning, long context. | |
added
benchmarks/hardware_manifest.py
+146 −0
@@ -0,0 +1,146 @@ | ||
| 1 | +#!/usr/bin/env python3 | |
| 2 | +# ============================================================================= | |
| 3 | +# Project : localvm-research | |
| 4 | +# File : benchmarks/hardware_manifest.py | |
| 5 | +# Purpose : macOS hardware/software fingerprint embedded in every result file | |
| 6 | +# Author : Simon-Pierre Boucher | |
| 7 | +# Contact : contact@spboucher.ai | |
| 8 | +# Created : 2026-08-11 | |
| 9 | +# Modified : 2026-08-11 | |
| 10 | +# Platform : macOS / Apple Silicon (arm64) | |
| 11 | +# License : All rights reserved (research code) | |
| 12 | +# ============================================================================= | |
| 13 | +"""Collect a reproducibility manifest for the current Mac. | |
| 14 | + | |
| 15 | +Records chip model, P/E core counts, GPU core count, unified memory size, | |
| 16 | +SSD model, macOS version, and versions of the key software stack (Python, | |
| 17 | +MLX, PyTorch, NumPy), plus the current git commit. Every benchmark result | |
| 18 | +JSON must embed this manifest (CLAUDE.md §0.2, §10). | |
| 19 | + | |
| 20 | +Usage: | |
| 21 | + python3 benchmarks/hardware_manifest.py # pretty-print JSON | |
| 22 | + from hardware_manifest import collect_manifest # programmatic use | |
| 23 | +""" | |
| 24 | + | |
| 25 | +from __future__ import annotations | |
| 26 | + | |
| 27 | +import json | |
| 28 | +import platform | |
| 29 | +import subprocess | |
| 30 | +import sys | |
| 31 | +from datetime import datetime, timezone | |
| 32 | + | |
| 33 | + | |
| 34 | +def _run(cmd: list[str]) -> str: | |
| 35 | + try: | |
| 36 | + return subprocess.run(cmd, capture_output=True, text=True, timeout=30).stdout.strip() | |
| 37 | + except (OSError, subprocess.TimeoutExpired): | |
| 38 | + return "" | |
| 39 | + | |
| 40 | + | |
| 41 | +def _sysctl(key: str) -> str: | |
| 42 | + return _run(["sysctl", "-n", key]) | |
| 43 | + | |
| 44 | + | |
| 45 | +def _sysctl_int(key: str) -> int | None: | |
| 46 | + val = _sysctl(key) | |
| 47 | + try: | |
| 48 | + return int(val) | |
| 49 | + except ValueError: | |
| 50 | + return None | |
| 51 | + | |
| 52 | + | |
| 53 | +def _gpu_cores() -> int | None: | |
| 54 | + """GPU core count via system_profiler (no sysctl key exposes it).""" | |
| 55 | + out = _run(["system_profiler", "SPDisplaysDataType", "-json"]) | |
| 56 | + try: | |
| 57 | + displays = json.loads(out)["SPDisplaysDataType"] | |
| 58 | + for gpu in displays: | |
| 59 | + cores = gpu.get("sppci_cores") | |
| 60 | + if cores is not None: | |
| 61 | + return int(cores) | |
| 62 | + except (json.JSONDecodeError, KeyError, ValueError, TypeError): | |
| 63 | + pass | |
| 64 | + return None | |
| 65 | + | |
| 66 | + | |
| 67 | +def _ssd_info() -> dict: | |
| 68 | + out = _run(["system_profiler", "SPNVMeDataType", "-json"]) | |
| 69 | + try: | |
| 70 | + items = json.loads(out)["SPNVMeDataType"] | |
| 71 | + for controller in items: | |
| 72 | + for dev in controller.get("_items", []): | |
| 73 | + return { | |
| 74 | + "model": dev.get("device_model", "").strip(), | |
| 75 | + "size": dev.get("size", ""), | |
| 76 | + "smart_status": dev.get("smart_status", ""), | |
| 77 | + } | |
| 78 | + except (json.JSONDecodeError, KeyError, TypeError): | |
| 79 | + pass | |
| 80 | + return {"model": None, "size": None, "smart_status": None} | |
| 81 | + | |
| 82 | + | |
| 83 | +def _pkg_version(module: str) -> str | None: | |
| 84 | + try: | |
| 85 | + from importlib.metadata import version | |
| 86 | + | |
| 87 | + return version(module) | |
| 88 | + except Exception: | |
| 89 | + return None | |
| 90 | + | |
| 91 | + | |
| 92 | +def _git_commit() -> dict: | |
| 93 | + commit = _run(["git", "rev-parse", "HEAD"]) | |
| 94 | + dirty = bool(_run(["git", "status", "--porcelain"])) | |
| 95 | + return {"commit": commit or None, "dirty_tree": dirty} | |
| 96 | + | |
| 97 | + | |
| 98 | +def _thermal_state() -> str | None: | |
| 99 | + # 'thermal pressure' via thermal level sysctl where available | |
| 100 | + lvl = _sysctl("machdep.xcpm.cpu_thermal_level") | |
| 101 | + return lvl or None | |
| 102 | + | |
| 103 | + | |
| 104 | +def collect_manifest() -> dict: | |
| 105 | + """Return the full hardware/software manifest as a dict.""" | |
| 106 | + mem_bytes = _sysctl_int("hw.memsize") or 0 | |
| 107 | + manifest = { | |
| 108 | + "author": "Simon-Pierre Boucher", | |
| 109 | + "contact": "contact@spboucher.ai", | |
| 110 | + "project": "localvm-research", | |
| 111 | + "collected_utc": datetime.now(timezone.utc).isoformat(), | |
| 112 | + "chip": { | |
| 113 | + "brand": _sysctl("machdep.cpu.brand_string"), | |
| 114 | + "arch": platform.machine(), | |
| 115 | + "cores_total": _sysctl_int("hw.ncpu"), | |
| 116 | + "cores_performance": _sysctl_int("hw.perflevel0.physicalcpu"), | |
| 117 | + "cores_efficiency": _sysctl_int("hw.perflevel1.physicalcpu"), | |
| 118 | + "gpu_cores": _gpu_cores(), | |
| 119 | + }, | |
| 120 | + "memory": { | |
| 121 | + "unified_bytes": mem_bytes, | |
| 122 | + "unified_gb": round(mem_bytes / 2**30, 1), | |
| 123 | + "pagesize": _sysctl_int("hw.pagesize"), | |
| 124 | + }, | |
| 125 | + "ssd": _ssd_info(), | |
| 126 | + "os": { | |
| 127 | + "product": _run(["sw_vers", "-productName"]), | |
| 128 | + "version": _run(["sw_vers", "-productVersion"]), | |
| 129 | + "build": _run(["sw_vers", "-buildVersion"]), | |
| 130 | + "kernel": platform.release(), | |
| 131 | + }, | |
| 132 | + "software": { | |
| 133 | + "python": sys.version.split()[0], | |
| 134 | + "mlx": _pkg_version("mlx"), | |
| 135 | + "mlx_lm": _pkg_version("mlx-lm"), | |
| 136 | + "torch": _pkg_version("torch"), | |
| 137 | + "numpy": _pkg_version("numpy"), | |
| 138 | + }, | |
| 139 | + "git": _git_commit(), | |
| 140 | + "thermal_level_at_collect": _thermal_state(), | |
| 141 | + } | |
| 142 | + return manifest | |
| 143 | + | |
| 144 | + | |
| 145 | +if __name__ == "__main__": | |
| 146 | + print(json.dumps(collect_manifest(), indent=2)) | |
added
docs/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: docs/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# docs | |
| 11 | + | |
| 12 | +Architecture docs, diagrams, final writeups. | |
added
experiments/micro/expA_weight_concentration/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expA_weight_concentration/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expA_weight_concentration | |
| 11 | + | |
| 12 | +Weight contribution concentration: can a subset of weight blocks reproduce most of each layer's output? | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expA_weight_concentration/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expA_weight_concentration/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expA_weight_concentration | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expA_weight_concentration/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expA_weight_concentration/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Weight contribution concentration: can a subset of weight blocks reproduce most of each layer's output? | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expA_weight_concentration. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expA_weight_concentration/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expA_weight_concentration/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expA_weight_concentration/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expA_weight_concentration | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expB_token_stability/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expB_token_stability/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expB_token_stability | |
| 11 | + | |
| 12 | +Stability of important weight blocks across consecutive tokens (Jaccard, transitions, working-set lifetime) | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expB_token_stability/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expB_token_stability/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expB_token_stability | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expB_token_stability/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expB_token_stability/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Stability of important weight blocks across consecutive tokens (Jaccard, transitions, working-set lifetime) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expB_token_stability. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expB_token_stability/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expB_token_stability/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expB_token_stability/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expB_token_stability | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expC_semantic_locality/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expC_semantic_locality/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expC_semantic_locality | |
| 11 | + | |
| 12 | +Cross-prompt semantic locality: do same-domain prompts reuse the same weight regions? | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expC_semantic_locality/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expC_semantic_locality/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expC_semantic_locality | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expC_semantic_locality/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expC_semantic_locality/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Cross-prompt semantic locality: do same-domain prompts reuse the same weight regions? | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expC_semantic_locality. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expC_semantic_locality/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expC_semantic_locality/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expC_semantic_locality/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expC_semantic_locality | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expD_progressive_reconstruction/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expD_progressive_reconstruction/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expD_progressive_reconstruction | |
| 11 | + | |
| 12 | +Progressive weight reconstruction: convergence of hidden-state/logit/decision error vs residual depth | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expD_progressive_reconstruction/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expD_progressive_reconstruction/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expD_progressive_reconstruction | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expD_progressive_reconstruction/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expD_progressive_reconstruction/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Progressive weight reconstruction: convergence of hidden-state/logit/decision error vs residual depth | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expD_progressive_reconstruction. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expD_progressive_reconstruction/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expD_progressive_reconstruction/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expD_progressive_reconstruction/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expD_progressive_reconstruction | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expE_partial_gemm/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expE_partial_gemm/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expE_partial_gemm | |
| 11 | + | |
| 12 | +Partial matrix multiplication: quality vs blocks evaluated, incl. a Metal kernel bandwidth check | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expE_partial_gemm/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expE_partial_gemm/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expE_partial_gemm | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expE_partial_gemm/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expE_partial_gemm/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Partial matrix multiplication: quality vs blocks evaluated, incl. a Metal kernel bandwidth check | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expE_partial_gemm. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expE_partial_gemm/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expE_partial_gemm/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expE_partial_gemm/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expE_partial_gemm | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expF_error_accumulation/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expF_error_accumulation/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expF_error_accumulation | |
| 11 | + | |
| 12 | +Error accumulation: which layers tolerate, amplify, or recover from controlled approximation | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expF_error_accumulation/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expF_error_accumulation/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expF_error_accumulation | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expF_error_accumulation/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expF_error_accumulation/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Error accumulation: which layers tolerate, amplify, or recover from controlled approximation | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expF_error_accumulation. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expF_error_accumulation/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expF_error_accumulation/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expF_error_accumulation/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expF_error_accumulation | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expG_decision_stability/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expG_decision_stability/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expG_decision_stability | |
| 11 | + | |
| 12 | +Decision stability: how many token decisions are stable before full precision is available | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expG_decision_stability/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expG_decision_stability/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expG_decision_stability | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expG_decision_stability/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expG_decision_stability/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: Decision stability: how many token decisions are stable before full precision is available | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expG_decision_stability. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expG_decision_stability/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expG_decision_stability/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expG_decision_stability/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expG_decision_stability | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
experiments/micro/expH_ssd_feasibility/README.md
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expH_ssd_feasibility/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# expH_ssd_feasibility | |
| 11 | + | |
| 12 | +SSD feasibility on macOS/APFS: measured random/sequential reads, F_NOCACHE, concurrent Metal compute | |
| 13 | + | |
| 14 | +Status: scaffolded 2026-08-11, not yet run. | |
added
experiments/micro/expH_ssd_feasibility/analysis.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expH_ssd_feasibility/analysis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Analysis — expH_ssd_feasibility | |
| 11 | + | |
| 12 | +*To be written after results exist. Must include the seven-field block and the evidence standard of CLAUDE.md §10.* | |
added
experiments/micro/expH_ssd_feasibility/benchmark.py
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : experiments/micro/expH_ssd_feasibility/benchmark.py | |
| 4 | +# Purpose : Benchmark runner: SSD feasibility on macOS/APFS: measured random/sequential reads, F_NOCACHE, concurrent Metal compute | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +"""Benchmark entry point for expH_ssd_feasibility. | |
| 14 | + | |
| 15 | +Must embed the hardware manifest in all result output | |
| 16 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 17 | +results/expH_ssd_feasibility/<timestamp>/. | |
| 18 | +""" | |
| 19 | + | |
| 20 | +import sys | |
| 21 | +from pathlib import Path | |
| 22 | + | |
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "benchmarks")) | |
| 24 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 25 | + | |
| 26 | + | |
| 27 | +def main() -> None: | |
| 28 | + manifest = collect_manifest() | |
| 29 | + raise NotImplementedError("experiment not yet implemented") | |
| 30 | + | |
| 31 | + | |
| 32 | +if __name__ == "__main__": | |
| 33 | + main() | |
added
experiments/micro/expH_ssd_feasibility/hypothesis.md
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: expH_ssd_feasibility/hypothesis | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Hypothesis — expH_ssd_feasibility | |
| 11 | + | |
| 12 | +```text | |
| 13 | +Hypothesis | |
| 14 | + <what we believe and why> | |
| 15 | + | |
| 16 | +Falsification criterion | |
| 17 | + <the concrete measurable outcome that would prove this wrong> | |
| 18 | + | |
| 19 | +Method | |
| 20 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 21 | + | |
| 22 | +Baseline | |
| 23 | + <what this is compared against — no straw men> | |
| 24 | + | |
| 25 | +Result | |
| 26 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 27 | + | |
| 28 | +Interpretation | |
| 29 | + <what the numbers mean; alternative explanations considered> | |
| 30 | + | |
| 31 | +Next experiment | |
| 32 | + <the most informative follow-up given this result> | |
| 33 | +``` | |
added
pyproject.toml
+39 −0
@@ -0,0 +1,39 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : pyproject.toml | |
| 4 | +# Purpose : Python project configuration (deps, ruff, pytest) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | + | |
| 13 | +[project] | |
| 14 | +name = "localvm" | |
| 15 | +version = "0.0.1" | |
| 16 | +description = "Research: out-of-core execution of large pretrained LLMs on consumer Apple Silicon" | |
| 17 | +authors = [{ name = "Simon-Pierre Boucher", email = "contact@spboucher.ai" }] | |
| 18 | +requires-python = ">=3.11" | |
| 19 | +dependencies = [ | |
| 20 | + "numpy", | |
| 21 | +] | |
| 22 | + | |
| 23 | +[project.optional-dependencies] | |
| 24 | +dev = ["ruff", "pytest"] | |
| 25 | +ml = ["mlx", "mlx-lm", "torch", "safetensors", "transformers"] | |
| 26 | + | |
| 27 | +[tool.setuptools.packages.find] | |
| 28 | +where = ["src"] | |
| 29 | + | |
| 30 | +[tool.ruff] | |
| 31 | +line-length = 100 | |
| 32 | +target-version = "py311" | |
| 33 | + | |
| 34 | +[tool.ruff.lint] | |
| 35 | +select = ["E", "F", "W", "I", "UP", "B"] | |
| 36 | + | |
| 37 | +[tool.pytest.ini_options] | |
| 38 | +testpaths = ["src", "experiments"] | |
| 39 | +python_files = ["test_*.py"] | |
added
research/LOG.md
+29 −0
@@ -0,0 +1,29 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: research/LOG (append-only research log) | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Research log (append-only) | |
| 11 | + | |
| 12 | +Format per entry: date/time (local, with timezone) · question · experiment · result · interpretation · decision. | |
| 13 | + | |
| 14 | +--- | |
| 15 | + | |
| 16 | +## 2026-08-11 23:40 EDT — Project bootstrap | |
| 17 | + | |
| 18 | +- **Question:** none (administrative). | |
| 19 | +- **Experiment:** none. | |
| 20 | +- **Result:** Repository initialized (git, `main`). Skeleton per charter §3 created. | |
| 21 | + Mandatory tooling written and functional: `tools/check_headers.py` (§0.1 enforcement), | |
| 22 | + `tools/new_experiment.py` (experiment scaffolding with seven-field hypothesis block), | |
| 23 | + `benchmarks/hardware_manifest.py` (macOS-native fingerprinting). | |
| 24 | +- **Host hardware discovered:** Apple M5 Max, 48 GB unified memory, macOS 27.0 (build 26A5388g) | |
| 25 | + — within the charter's target class (16–64 GB Apple Silicon). | |
| 26 | +- **Interpretation:** n/a. | |
| 27 | +- **Decision:** Begin Phase 1 (ultra-deep literature research, charter §4) immediately, | |
| 28 | + fanning out across the ten mandated areas (§4.1–§4.10). Deliverables: per-topic notes in | |
| 29 | + `research/notes/`, every source logged in `research/bibliography.md` with URL and access date. | |
added
research/bibliography.md
+15 −0
@@ -0,0 +1,15 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: research/bibliography | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# Bibliography | |
| 11 | + | |
| 12 | +Every consulted source, with URL and access date. Grouped by theme (mirrors `research/notes/`). | |
| 13 | +Entries are appended as Phase 1 progresses; nothing is deleted. | |
| 14 | + | |
| 15 | +*(Populated during Phase 1 — see per-theme sections below as they are added.)* | |
added
research/notes/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: research/notes/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# research/notes | |
| 11 | + | |
| 12 | +Per-topic Phase 1 reading notes (one file per theme). | |
added
results/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: results/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# results | |
| 11 | + | |
| 12 | +Raw and aggregated results, results/<experiment_id>/<timestamp>/ (generated files exempt from headers). | |
added
src/kernels/README.md
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +--- | |
| 2 | +project: localvm-research | |
| 3 | +document: src/kernels/README | |
| 4 | +author: Simon-Pierre Boucher | |
| 5 | +contact: contact@spboucher.ai | |
| 6 | +created: 2026-08-11 | |
| 7 | +status: draft | |
| 8 | +--- | |
| 9 | + | |
| 10 | +# src/kernels | |
| 11 | + | |
| 12 | +Custom Metal (.metal) and C++ kernels. | |
added
src/localvm/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/__init__.py | |
| 4 | +# Purpose : localvm core library package root | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""localvm core library package root.""" | |
added
src/localvm/backends/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/backends/__init__.py | |
| 4 | +# Purpose : Compute backends package | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Compute backends package.""" | |
added
src/localvm/backends/cpu_backend/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/backends/cpu_backend/__init__.py | |
| 4 | +# Purpose : Accelerate / NEON CPU compute path | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Accelerate / NEON CPU compute path.""" | |
added
src/localvm/backends/cuda_optional/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/backends/cuda_optional/__init__.py | |
| 4 | +# Purpose : Isolated optional CUDA validation path (never a core dependency) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Isolated optional CUDA validation path (never a core dependency).""" | |
added
src/localvm/backends/mlx_backend/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/backends/mlx_backend/__init__.py | |
| 4 | +# Purpose : MLX / Metal primary compute path | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""MLX / Metal primary compute path.""" | |
added
src/localvm/backends/mps_backend/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/backends/mps_backend/__init__.py | |
| 4 | +# Purpose : PyTorch-MPS compute path | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""PyTorch-MPS compute path.""" | |
added
src/localvm/instrumentation/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/instrumentation/__init__.py | |
| 4 | +# Purpose : macOS-native measurement (mach task_info, vm_stat, fs_usage, powermetrics) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""macOS-native measurement (mach task_info, vm_stat, fs_usage, powermetrics).""" | |
added
src/localvm/models/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/models/__init__.py | |
| 4 | +# Purpose : Model loading and checkpoint parsing (safetensors/GGUF) | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Model loading and checkpoint parsing (safetensors/GGUF).""" | |
added
src/localvm/quality/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/quality/__init__.py | |
| 4 | +# Purpose : Quality metrics: perplexity, KL divergence, decision stability | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Quality metrics: perplexity, KL divergence, decision stability.""" | |
added
src/localvm/runtime/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/runtime/__init__.py | |
| 4 | +# Purpose : Runtime: paging, scheduling, caching, prediction | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Runtime: paging, scheduling, caching, prediction.""" | |
added
src/localvm/transforms/__init__.py
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +# ============================================================================= | |
| 2 | +# Project : localvm-research | |
| 3 | +# File : src/localvm/transforms/__init__.py | |
| 4 | +# Purpose : Post-training transforms: quantization, decomposition, encodings | |
| 5 | +# Author : Simon-Pierre Boucher | |
| 6 | +# Contact : contact@spboucher.ai | |
| 7 | +# Created : 2026-08-11 | |
| 8 | +# Modified : 2026-08-11 | |
| 9 | +# Platform : macOS / Apple Silicon (arm64) | |
| 10 | +# License : All rights reserved (research code) | |
| 11 | +# ============================================================================= | |
| 12 | +"""Post-training transforms: quantization, decomposition, encodings.""" | |
added
tools/check_headers.py
+143 −0
@@ -0,0 +1,143 @@ | ||
| 1 | +#!/usr/bin/env python3 | |
| 2 | +# ============================================================================= | |
| 3 | +# Project : localvm-research | |
| 4 | +# File : tools/check_headers.py | |
| 5 | +# Purpose : CI-style enforcement of the mandatory author header (CLAUDE.md §0.1) | |
| 6 | +# Author : Simon-Pierre Boucher | |
| 7 | +# Contact : contact@spboucher.ai | |
| 8 | +# Created : 2026-08-11 | |
| 9 | +# Modified : 2026-08-11 | |
| 10 | +# Platform : macOS / Apple Silicon (arm64) | |
| 11 | +# License : All rights reserved (research code) | |
| 12 | +# ============================================================================= | |
| 13 | +"""Fail (exit 1) if any tracked source file lacks a conforming author header. | |
| 14 | + | |
| 15 | +Usage: | |
| 16 | + python3 tools/check_headers.py # check all git-tracked files | |
| 17 | + python3 tools/check_headers.py FILE... # check specific files | |
| 18 | + | |
| 19 | +Rules enforced (see CLAUDE.md §0.1): | |
| 20 | + * Comment-style sources (.py .sh .zsh .yaml .yml .toml .cff Makefile | |
| 21 | + CMakeLists.txt) must contain the '#'-style header block near the top. | |
| 22 | + * C-family sources (.c .cpp .h .hpp .metal .swift .m .mm) must contain the | |
| 23 | + '//'-style header block near the top. | |
| 24 | + * Markdown documents must begin with YAML front matter declaring | |
| 25 | + project/author/contact. | |
| 26 | + * A shebang line may precede the header. | |
| 27 | + | |
| 28 | +Exemptions: generated results under results/, LICENSE, .gitignore is checked | |
| 29 | +(it supports comments), CLAUDE.md (the charter predates the convention and is | |
| 30 | +the specification itself). | |
| 31 | +""" | |
| 32 | + | |
| 33 | +from __future__ import annotations | |
| 34 | + | |
| 35 | +import subprocess | |
| 36 | +import sys | |
| 37 | +from pathlib import Path | |
| 38 | + | |
| 39 | +REPO_ROOT = Path(__file__).resolve().parent.parent | |
| 40 | + | |
| 41 | +REQUIRED_FIELDS = ("Project", "File", "Purpose", "Author", "Contact", | |
| 42 | + "Created", "Modified", "Platform", "License") | |
| 43 | +AUTHOR = "Simon-Pierre Boucher" | |
| 44 | +CONTACT = "contact@spboucher.ai" | |
| 45 | + | |
| 46 | +HASH_EXTS = {".py", ".sh", ".zsh", ".bash", ".yaml", ".yml", ".toml", ".cff"} | |
| 47 | +SLASH_EXTS = {".c", ".cc", ".cpp", ".h", ".hpp", ".metal", ".swift", ".m", ".mm"} | |
| 48 | +HASH_NAMES = {"Makefile", "CMakeLists.txt", ".gitignore"} | |
| 49 | + | |
| 50 | +EXEMPT_NAMES = {"LICENSE", "CLAUDE.md", "MEMORY.md"} | |
| 51 | +EXEMPT_DIRS = {"results"} | |
| 52 | +# How many leading lines to scan for the header block (allows shebang etc.). | |
| 53 | +SCAN_LINES = 20 | |
| 54 | + | |
| 55 | + | |
| 56 | +def tracked_files() -> list[Path]: | |
| 57 | + out = subprocess.run( | |
| 58 | + ["git", "ls-files"], cwd=REPO_ROOT, capture_output=True, text=True, check=True | |
| 59 | + ).stdout | |
| 60 | + return [REPO_ROOT / line for line in out.splitlines() if line.strip()] | |
| 61 | + | |
| 62 | + | |
| 63 | +def is_exempt(path: Path) -> bool: | |
| 64 | + rel = path.relative_to(REPO_ROOT) | |
| 65 | + if rel.name in EXEMPT_NAMES: | |
| 66 | + return True | |
| 67 | + return bool(rel.parts and rel.parts[0] in EXEMPT_DIRS) | |
| 68 | + | |
| 69 | + | |
| 70 | +def check_comment_header(lines: list[str], prefix: str) -> list[str]: | |
| 71 | + """Check for a comment-style header with all required fields near the top.""" | |
| 72 | + head = "\n".join(lines[:SCAN_LINES]) | |
| 73 | + errors = [] | |
| 74 | + for field in REQUIRED_FIELDS: | |
| 75 | + if f"{prefix} {field}" not in head and f"{prefix} {field}" not in head: | |
| 76 | + errors.append(f"missing header field: {field}") | |
| 77 | + if AUTHOR not in head: | |
| 78 | + errors.append(f"missing author name '{AUTHOR}'") | |
| 79 | + if CONTACT not in head: | |
| 80 | + errors.append(f"missing contact '{CONTACT}'") | |
| 81 | + return errors | |
| 82 | + | |
| 83 | + | |
| 84 | +def check_markdown_front_matter(lines: list[str]) -> list[str]: | |
| 85 | + if not lines or lines[0].strip() != "---": | |
| 86 | + return ["markdown file must start with YAML front matter (---)"] | |
| 87 | + errors = [] | |
| 88 | + try: | |
| 89 | + end = next(i for i in range(1, min(len(lines), SCAN_LINES)) if lines[i].strip() == "---") | |
| 90 | + except StopIteration: | |
| 91 | + return ["unterminated YAML front matter"] | |
| 92 | + block = "\n".join(lines[1:end]) | |
| 93 | + for key in ("project: localvm-research", f"author: {AUTHOR}", f"contact: {CONTACT}"): | |
| 94 | + if key not in block: | |
| 95 | + errors.append(f"front matter missing '{key}'") | |
| 96 | + return errors | |
| 97 | + | |
| 98 | + | |
| 99 | +def check_file(path: Path) -> list[str]: | |
| 100 | + try: | |
| 101 | + text = path.read_text(encoding="utf-8", errors="replace") | |
| 102 | + except OSError as exc: | |
| 103 | + return [f"unreadable: {exc}"] | |
| 104 | + lines = text.splitlines() | |
| 105 | + if lines and lines[0].startswith("#!"): | |
| 106 | + lines = lines[1:] | |
| 107 | + | |
| 108 | + name, ext = path.name, path.suffix | |
| 109 | + if ext in HASH_EXTS or name in HASH_NAMES: | |
| 110 | + return check_comment_header(lines, "#") | |
| 111 | + if ext in SLASH_EXTS: | |
| 112 | + return check_comment_header(lines, "//") | |
| 113 | + if ext == ".md": | |
| 114 | + return check_markdown_front_matter(lines) | |
| 115 | + return [] # other file types are not subject to the header rule | |
| 116 | + | |
| 117 | + | |
| 118 | +def main(argv: list[str]) -> int: | |
| 119 | + paths = [Path(p).resolve() for p in argv] if argv else tracked_files() | |
| 120 | + failures: dict[str, list[str]] = {} | |
| 121 | + checked = 0 | |
| 122 | + for path in paths: | |
| 123 | + if not path.is_file() or is_exempt(path): | |
| 124 | + continue | |
| 125 | + errors = check_file(path) | |
| 126 | + if path.suffix in HASH_EXTS | SLASH_EXTS | {".md"} or path.name in HASH_NAMES: | |
| 127 | + checked += 1 | |
| 128 | + if errors: | |
| 129 | + failures[str(path.relative_to(REPO_ROOT))] = errors | |
| 130 | + | |
| 131 | + if failures: | |
| 132 | + print(f"HEADER CHECK FAILED — {len(failures)} non-conforming file(s):\n") | |
| 133 | + for rel, errors in sorted(failures.items()): | |
| 134 | + print(f" {rel}") | |
| 135 | + for err in errors: | |
| 136 | + print(f" - {err}") | |
| 137 | + return 1 | |
| 138 | + print(f"Header check passed ({checked} files checked).") | |
| 139 | + return 0 | |
| 140 | + | |
| 141 | + | |
| 142 | +if __name__ == "__main__": | |
| 143 | + sys.exit(main(sys.argv[1:])) | |
added
tools/new_experiment.py
+148 −0
@@ -0,0 +1,148 @@ | ||
| 1 | +#!/usr/bin/env python3 | |
| 2 | +# ============================================================================= | |
| 3 | +# Project : localvm-research | |
| 4 | +# File : tools/new_experiment.py | |
| 5 | +# Purpose : Scaffold a header-compliant experiment directory (CLAUDE.md §3, §10) | |
| 6 | +# Author : Simon-Pierre Boucher | |
| 7 | +# Contact : contact@spboucher.ai | |
| 8 | +# Created : 2026-08-11 | |
| 9 | +# Modified : 2026-08-11 | |
| 10 | +# Platform : macOS / Apple Silicon (arm64) | |
| 11 | +# License : All rights reserved (research code) | |
| 12 | +# ============================================================================= | |
| 13 | +"""Scaffold a new experiment directory with the mandatory structure. | |
| 14 | + | |
| 15 | +Creates: README.md, hypothesis.md (seven-field scientific block), benchmark.py, | |
| 16 | +implementation/, results/, analysis.md — all with conforming author headers. | |
| 17 | + | |
| 18 | +Usage: | |
| 19 | + python3 tools/new_experiment.py experiments/micro/expX_name "One-line purpose" | |
| 20 | + python3 tools/new_experiment.py experiments/candidate_04 "Candidate: ..." | |
| 21 | +""" | |
| 22 | + | |
| 23 | +from __future__ import annotations | |
| 24 | + | |
| 25 | +import sys | |
| 26 | +from datetime import date | |
| 27 | +from pathlib import Path | |
| 28 | + | |
| 29 | +REPO_ROOT = Path(__file__).resolve().parent.parent | |
| 30 | +TODAY = date.today().isoformat() | |
| 31 | + | |
| 32 | +PY_HEADER = """\ | |
| 33 | +# ============================================================================= | |
| 34 | +# Project : localvm-research | |
| 35 | +# File : {rel} | |
| 36 | +# Purpose : {purpose} | |
| 37 | +# Author : Simon-Pierre Boucher | |
| 38 | +# Contact : contact@spboucher.ai | |
| 39 | +# Created : {today} | |
| 40 | +# Modified : {today} | |
| 41 | +# Platform : macOS / Apple Silicon (arm64) | |
| 42 | +# License : All rights reserved (research code) | |
| 43 | +# ============================================================================= | |
| 44 | +""" | |
| 45 | + | |
| 46 | +MD_HEADER = """\ | |
| 47 | +--- | |
| 48 | +project: localvm-research | |
| 49 | +document: {doc} | |
| 50 | +author: Simon-Pierre Boucher | |
| 51 | +contact: contact@spboucher.ai | |
| 52 | +created: {today} | |
| 53 | +status: draft | |
| 54 | +--- | |
| 55 | +""" | |
| 56 | + | |
| 57 | +HYPOTHESIS_BODY = """ | |
| 58 | +# Hypothesis — {name} | |
| 59 | + | |
| 60 | +```text | |
| 61 | +Hypothesis | |
| 62 | + <what we believe and why> | |
| 63 | + | |
| 64 | +Falsification criterion | |
| 65 | + <the concrete measurable outcome that would prove this wrong> | |
| 66 | + | |
| 67 | +Method | |
| 68 | + <exact procedure, model(s), data, seeds, measurement points> | |
| 69 | + | |
| 70 | +Baseline | |
| 71 | + <what this is compared against — no straw men> | |
| 72 | + | |
| 73 | +Result | |
| 74 | + <filled after the run: numbers, with mean/median/std and run count> | |
| 75 | + | |
| 76 | +Interpretation | |
| 77 | + <what the numbers mean; alternative explanations considered> | |
| 78 | + | |
| 79 | +Next experiment | |
| 80 | + <the most informative follow-up given this result> | |
| 81 | +``` | |
| 82 | +""" | |
| 83 | + | |
| 84 | +BENCHMARK_BODY = ''' | |
| 85 | +"""Benchmark entry point for {name}. | |
| 86 | + | |
| 87 | +Must embed the hardware manifest in all result output | |
| 88 | +(see benchmarks/hardware_manifest.py) and write results to | |
| 89 | +results/{name}/<timestamp>/. | |
| 90 | +""" | |
| 91 | + | |
| 92 | +import sys | |
| 93 | +from pathlib import Path | |
| 94 | + | |
| 95 | +sys.path.insert(0, str(Path(__file__).resolve().parents[{depth}] / "benchmarks")) | |
| 96 | +from hardware_manifest import collect_manifest # noqa: E402 | |
| 97 | + | |
| 98 | + | |
| 99 | +def main() -> None: | |
| 100 | + manifest = collect_manifest() | |
| 101 | + raise NotImplementedError("experiment not yet implemented") | |
| 102 | + | |
| 103 | + | |
| 104 | +if __name__ == "__main__": | |
| 105 | + main() | |
| 106 | +''' | |
| 107 | + | |
| 108 | + | |
| 109 | +def scaffold(exp_dir: Path, purpose: str) -> None: | |
| 110 | + if exp_dir.exists() and any(exp_dir.iterdir()): | |
| 111 | + sys.exit(f"error: {exp_dir} already exists and is not empty") | |
| 112 | + name = exp_dir.name | |
| 113 | + rel = exp_dir.relative_to(REPO_ROOT) | |
| 114 | + (exp_dir / "implementation").mkdir(parents=True, exist_ok=True) | |
| 115 | + (exp_dir / "results").mkdir(exist_ok=True) | |
| 116 | + | |
| 117 | + def md(doc: str) -> str: | |
| 118 | + return MD_HEADER.format(doc=doc, today=TODAY) | |
| 119 | + | |
| 120 | + (exp_dir / "README.md").write_text( | |
| 121 | + md(f"{name}/README") + f"\n# {name}\n\n{purpose}\n\nStatus: scaffolded {TODAY}, not yet run.\n" | |
| 122 | + ) | |
| 123 | + (exp_dir / "hypothesis.md").write_text( | |
| 124 | + md(f"{name}/hypothesis") + HYPOTHESIS_BODY.format(name=name) | |
| 125 | + ) | |
| 126 | + (exp_dir / "analysis.md").write_text( | |
| 127 | + md(f"{name}/analysis") + f"\n# Analysis — {name}\n\n*To be written after results exist. " | |
| 128 | + "Must include the seven-field block and the evidence standard of CLAUDE.md §10.*\n" | |
| 129 | + ) | |
| 130 | + depth = len(rel.parts) # parents[] index up to repo root | |
| 131 | + (exp_dir / "benchmark.py").write_text( | |
| 132 | + PY_HEADER.format(rel=rel / "benchmark.py", purpose=f"Benchmark runner: {purpose}", today=TODAY) | |
| 133 | + + BENCHMARK_BODY.format(name=name, depth=depth) | |
| 134 | + ) | |
| 135 | + print(f"scaffolded {rel} ({purpose})") | |
| 136 | + | |
| 137 | + | |
| 138 | +def main() -> None: | |
| 139 | + if len(sys.argv) < 3: | |
| 140 | + sys.exit(__doc__) | |
| 141 | + exp_dir = (REPO_ROOT / sys.argv[1]).resolve() | |
| 142 | + if REPO_ROOT not in exp_dir.parents: | |
| 143 | + sys.exit("error: experiment directory must live inside the repository") | |
| 144 | + scaffold(exp_dir, sys.argv[2]) | |
| 145 | + | |
| 146 | + | |
| 147 | +if __name__ == "__main__": | |
| 148 | + main() | |
| 149 | ||