spb/localvm-research Public License
Running LLMs larger than memory on a consumer Mac — falsification-driven research: margin-gated deferred refinement, out-of-core verification on Apple Silicon. TR-01 published.
Python 63.2%
JavaScript 23.5%
CSS 11.8%
Shell 0.9%
Makefile 0.5%
1// ============================================================================2// Project : localvm-research3// File : web/lib/content.js4// Purpose : Content index over the synced research-repo snapshot (content/)5// Author : Simon-Pierre Boucher6// Contact : contact@spboucher.ai7// Created : 2026-08-128// Modified : 2026-08-129// Platform : macOS / Apple Silicon (arm64) — Node.js10// License : All rights reserved (research code)11// ============================================================================12"use strict";1314const fs = require("fs");15const path = require("path");16const matter = require("gray-matter");1718const CONTENT_ROOT = path.join(__dirname, "..", "content");1920const TEXT_EXT = new Set([21 ".md", ".py", ".sh", ".toml", ".yaml", ".yml", ".cff", ".json",22 ".js", ".css", ".metal", ".cpp", ".h", ".hpp", ".swift", ".m", ".txt", ".log",23]);2425/** Resolve a repo-relative path safely inside content/, or return null. */26function safeResolve(rel) {27 const abs = path.resolve(CONTENT_ROOT, rel);28 if (!abs.startsWith(CONTENT_ROOT + path.sep) && abs !== CONTENT_ROOT) return null;29 return abs;30}3132function exists(rel) {33 const abs = safeResolve(rel);34 return abs !== null && fs.existsSync(abs);35}3637function readText(rel) {38 const abs = safeResolve(rel);39 if (!abs || !fs.existsSync(abs) || !fs.statSync(abs).isFile()) return null;40 return fs.readFileSync(abs, "utf8");41}4243/** Read a markdown file, returning { data (front matter), content }. */44function readMarkdown(rel) {45 const raw = readText(rel);46 if (raw === null) return null;47 try {48 return matter(raw);49 } catch {50 return { data: {}, content: raw };51 }52}5354/** List a directory inside content/: [{name, rel, dir, size}] */55function listDir(rel) {56 const abs = safeResolve(rel || ".");57 if (!abs || !fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) return null;58 return fs59 .readdirSync(abs)60 .filter((n) => !n.startsWith(".") && n !== "node_modules")61 .map((n) => {62 const st = fs.statSync(path.join(abs, n));63 return {64 name: n,65 rel: path.posix.join(rel || "", n),66 dir: st.isDirectory(),67 size: st.size,68 };69 })70 .sort((a, b) => (a.dir !== b.dir ? (a.dir ? -1 : 1) : a.name.localeCompare(b.name)));71}7273/** Recursively collect files under rel matching a predicate. */74function walk(rel, predicate, out = []) {75 const entries = listDir(rel);76 if (!entries) return out;77 for (const e of entries) {78 if (e.dir) walk(e.rel, predicate, out);79 else if (predicate(e)) out.push(e);80 }81 return out;82}8384function isTextFile(rel) {85 return TEXT_EXT.has(path.extname(rel).toLowerCase()) || path.basename(rel) === "Makefile";86}8788/** Parse research/LOG.md into entries [{title, body}] (## headings). */89function parseLogEntries() {90 const md = readMarkdown("research/LOG.md");91 if (!md) return [];92 const parts = md.content.split(/^## /m).slice(1);93 return parts.map((p) => {94 const nl = p.indexOf("\n");95 return { title: p.slice(0, nl).trim(), body: p.slice(nl + 1).replace(/^---\s*$/m, "").trim() };96 });97}9899/** Experiment cards: micro experiments + candidates. */100function listExperiments() {101 const out = [];102 for (const base of ["experiments/micro", "experiments"]) {103 const entries = listDir(base) || [];104 for (const e of entries) {105 if (!e.dir || e.name === "micro") continue;106 const readme = readMarkdown(path.posix.join(e.rel, "README.md"));107 const hasAnalysis = (readText(path.posix.join(e.rel, "analysis.md")) || "").length > 400;108 const runs = listResultRuns().filter((r) => r.experiment === e.name || r.experiment.startsWith(e.name + "_"));109 let purpose = "";110 if (readme) {111 const line = readme.content.split("\n").find((l) => l.trim() && !l.startsWith("#"));112 purpose = line ? line.trim() : "";113 }114 out.push({115 id: e.name,116 rel: e.rel,117 purpose,118 status: runs.length > 0 && hasAnalysis ? "completed" : runs.length > 0 ? "has results" : "scaffolded",119 runs: runs.length,120 });121 }122 }123 return out;124}125126/** Result runs: results/<experiment>/<timestamp>/*.json */127function listResultRuns() {128 const out = [];129 for (const exp of listDir("results") || []) {130 if (!exp.dir) continue;131 for (const run of listDir(exp.rel) || []) {132 if (!run.dir) continue;133 const files = (listDir(run.rel) || []).filter((f) => !f.dir);134 out.push({ experiment: exp.name, timestamp: run.name, rel: run.rel, files });135 }136 }137 return out.sort((a, b) => b.timestamp.localeCompare(a.timestamp));138}139140function readJson(rel) {141 const raw = readText(rel);142 if (raw === null) return null;143 try {144 return JSON.parse(raw);145 } catch {146 return null;147 }148}149150/** Build info written by sync-content.sh (commit, counts, date). */151function buildInfo() {152 return readJson("build-info.json") || {};153}154155/** Site-wide stats for the home page. */156function stats() {157 const bib = readText("research/bibliography.md") || "";158 const sources = bib.split("\n").filter((l) => l.trim().startsWith("- ")).length;159 const gapsDoc = readText("research/research_gaps.md") || "";160 const gaps = (gapsDoc.match(/^#{2,3}\s+G\d{2}/gm) || []).length;161 const experiments = listExperiments();162 const notes = (listDir("research/notes") || []).filter((f) => f.name.endsWith(".md") && f.name !== "README.md").length;163 return {164 sources,165 gaps,166 notes,167 experiments: experiments.length,168 experimentsDone: experiments.filter((e) => e.status === "completed").length,169 resultRuns: listResultRuns().length,170 logEntries: parseLogEntries().length,171 build: buildInfo(),172 };173}174175/** Latest expH results for the home-page chart: cold random cells. */176function expHChartData() {177 const runs = listResultRuns().filter((r) => r.experiment === "expH_ssd_feasibility");178 if (!runs.length) return null;179 const data = readJson(path.posix.join(runs[0].rel, "results.json"));180 if (!data) return null;181 const cells = (data.cells || []).filter(182 (c) => c.nocache && !c.gpu_load && c.pattern === "random" && c.block_bytes <= 1 << 20183 );184 const series = {};185 for (const c of cells) {186 (series[c.threads] ||= []).push({ block: c.block_bytes, mbps: c.mb_per_s_mean });187 }188 for (const k of Object.keys(series)) series[k].sort((a, b) => a.block - b.block);189 return { series, run: runs[0].timestamp, manifest: data.manifest || {} };190}191192module.exports = {193 CONTENT_ROOT,194 safeResolve,195 exists,196 readText,197 readMarkdown,198 readJson,199 listDir,200 walk,201 isTextFile,202 parseLogEntries,203 listExperiments,204 listResultRuns,205 buildInfo,206 stats,207 expHChartData,208};209