1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>memgraph — what it is, why it exists & how to use it</title>
<style>
:root{--bg:#0a0f14;--bg2:#0b1219;--card:#101a24;--line:#1d2c3a;--tx:#dbe7f0;--mut:#8aa0b4;--cy:#22d3ee;--am:#f59e0b;--vi:#a78bfa;--gr:#34d399;--rd:#f87171}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--tx);font:16px/1.65 -apple-system,"Segoe UI",Roboto,system-ui,sans-serif}
.wrap{max-width:920px;margin:0 auto;padding:0 22px 70px}
header{padding:46px 0 26px;border-bottom:1px solid var(--line)}
h1{font-size:44px;margin:0 0 6px;letter-spacing:-1px}
h1 .dot{color:var(--cy)}
.sub{color:var(--mut);font-size:19px;margin:0 0 16px;max-width:660px}
.badges{display:flex;flex-wrap:wrap;gap:8px}
.badge{border:1px solid var(--line);background:var(--bg2);border-radius:99px;padding:4px 12px;font:12.5px ui-monospace,Consolas,monospace;color:var(--mut)}
.badge b{color:var(--cy);font-weight:600}
nav{display:flex;flex-wrap:wrap;gap:6px;padding:14px 0;border-bottom:1px solid var(--line);position:sticky;top:0;background:rgba(10,15,20,.94);z-index:5}
nav a{color:var(--mut);text-decoration:none;font-size:13.5px;border:1px solid transparent;border-radius:8px;padding:4px 10px}
nav a:hover{color:var(--cy);border-color:var(--line)}
section{padding:34px 0 6px}
h2{font-size:26px;margin:0 0 14px;letter-spacing:-.3px}
h2 .n{color:var(--cy);font-family:ui-monospace,monospace;font-size:15px;margin-right:10px}
h3{font-size:17px;margin:26px 0 8px;color:#fff}
p{margin:9px 0}
.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:18px 20px;margin:16px 0}
.card b{color:#fff}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:720px){.grid{grid-template-columns:1fr}}
code{font-family:ui-monospace,Consolas,monospace;font-size:.9em;background:var(--bg2);border:1px solid var(--line);border-radius:6px;padding:1px 6px;color:var(--cy)}
pre{font-family:ui-monospace,Consolas,monospace;font-size:12.8px;background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:14px 16px;overflow:auto;line-height:1.55;color:#b8cfe0}
table{border-collapse:collapse;width:100%;font-size:14.5px}
td,th{border-bottom:1px solid var(--line);padding:9px 10px;text-align:left;vertical-align:top}
th{color:var(--mut);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.6px}
ul{margin:8px 0;padding-left:22px}
li{margin:6px 0}
.mut{color:var(--mut)}
.note{border-left:3px solid var(--cy);background:var(--bg2);padding:10px 14px;border-radius:0 10px 10px 0;font-size:14.5px;color:#b8cfe0;margin:14px 0}
.warn{border-left-color:var(--am)}
canvas#demo{width:100%;height:440px;display:block;background:var(--bg2);border:1px solid var(--line);border-radius:14px;touch-action:none;cursor:grab;margin-top:8px}
.legend{display:flex;flex-wrap:wrap;gap:14px;font-size:12.5px;color:var(--mut);margin-top:10px;font-family:ui-monospace,monospace}
.sw{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:6px;vertical-align:-1px}
.ok{color:var(--gr);font-weight:600}.pend{color:var(--am);font-weight:600}
footer{margin-top:50px;padding-top:18px;border-top:1px solid var(--line);color:var(--mut);font-size:13px}
</style></head><body><div class="wrap">
<header>
<h1>memgraph<span class="dot">_</span></h1>
<p class="sub">Your newOS4 system drawn as a <b>map of relationships</b> instead of a tree of folders.</p>
<div class="badges">
<span class="badge">nodes <b>228</b></span>
<span class="badge">edges <b>321</b></span>
<span class="badge">newOS4 <b>v4.6.26</b></span>
<span class="badge">system-wide <b>448 files · 45 modules · 28 skills · 49 agents</b></span>
<span class="badge">updated <b>2026-10-17</b></span>
</div>
</header>
<nav>
<a href="#what">what</a><a href="#why">why</a><a href="#data">data model</a><a href="#how">how to use</a><a href="#viewer">viewer controls</a><a href="#export">export & the bake</a><a href="#demo">try it</a><a href="#status">status tonight</a>
</nav>
<section id="what"><h2><span class="n">01</span>What is memgraph?</h2>
<p>The <b>memory graph</b> (<code>memgraph</code>) is a live knowledge graph of your system itself. Every file, skill, module, task and agent becomes a <b>node</b>; every relationship between them — references, accesses, dependencies, co-use — becomes an <b>edge</b> carrying a type, a weight and timestamps.</p>
<p>Right now it holds <b>228 nodes and 321 edges</b>, kept fresh by the <code>MemoryGraphModule</code> as you work. Nothing is hand-tagged: the map draws itself from ordinary activity, stored in the VFS at <code>/.memory_graph/nodes.json</code> and <code>/.memory_graph/edges.json</code>.</p>
<p>It already knows things like: your most-accessed file tonight is <code>floatimg-buttons.html</code> (16 accesses), with <code>floating-ui.md</code> trailing at 6, and that the recent tasks were “bake /memgraph-today.html”, “use agents” and “write the memgraph guide”. That little context block the AI sees at the top of every turn? It is read from this graph — it is <b>shared memory</b> between you and the machine.</p>
<div class="card"><b>One-line analogy:</b> a folder tree tells you a thing's <i>street address</i>; the memory graph tells you its <i>friendships</i>. “Where is floating-ui.md?” is a folder question. “What is floating-ui.md used by, how often, and since when?” is a graph question.</div>
</section>
<section id="why"><h2><span class="n">02</span>Why a graph?</h2>
<div class="grid">
<div class="card"><b>Meaning over location.</b><br>Folders show paths; the graph shows relations. You find things by what they connect to, not by remembering where they were filed.</div>
<div class="card"><b>Use is visible.</b><br>Every access bumps a counter. Hotspots (<code>floatimg-buttons.html</code> ×16) pop out by node size and edge thickness; dead orphans sit as lonely islands.</div>
<div class="card"><b>Time is a dimension.</b><br>Nodes and edges carry <code>created</code> / last-used stamps — so the viewer can scrub back to any moment and replay history. You can literally watch your system grow.</div>
<div class="card"><b>Failures are marked.</b><br>Broken or failed items wear a red <span style="color:var(--rd)">✕</span>. Dead references and failed jobs stand out immediately instead of hiding in logs.</div>
<div class="card"><b>It powers the AI.</b><br>The “Memory Graph Context” (recent tasks, most-accessed files) shown to the agent each turn comes straight from this graph. Ask the agent “what are my most used files?” — it answers from here.</div>
<div class="card"><b>Self-maintaining.</b><br>Edges grow as a side effect of doing work. No manual curation, no tagging chores — the map updates itself while you build.</div>
</div>
</section>
<section id="data"><h2><span class="n">03</span>The data model</h2>
<pre>node { id, type, label, access_count, created | updated }
edge { source, target, type, weight, use_count, created | last_used }
storage : /.memory_graph/nodes.json · /.memory_graph/edges.json (VFS)
loader : MemoryGraphModule → VFS/localStorage → IndexedDB → embedded snapshot (fallback)
compact snapshot format (used when baking a standalone copy):
n: [ id, type, label, accesses, created ]
e: [ srcIdx, tgtIdx, type, weight, uses, born ] // edges reference nodes by array index</pre>
<p class="mut">Node types observed in your graph: <b>file</b>, <b>skill</b>, <b>module</b>, <b>task</b> — plus system/storage entities. An edge's <code>type</code> is the relationship kind; <code>weight</code> and <code>use_count</code> say how strong and how often.</p>
</section>
<section id="how"><h2><span class="n">04</span>How to use it</h2>
<h3>The command</h3>
<p>Run <code>memgraph</code> in the terminal (it's listed under <i>Other</i> in <code>help</code>). The module reports the graph's stats — node and edge counts, recency — and manages the data files under <code>/.memory_graph/</code>.</p>
<h3>The visual viewers (HTML)</h3>
<ul>
<li><code>/memgraph.html</code> — the <b>baked</b> standalone map (45 KB). Opens anywhere: inside newOS4, in the preview, or downloaded to any machine. This is the one that just works.</li>
<li><code>/memgraph-today.html</code> — today's view, <b>not yet baked</b> (21.5 KB). Only renders inside newOS4 until a snapshot is baked into it (see <a href="#export">Export & the bake</a>).</li>
</ul>
<p>Both viewers are <b>force-directed</b>: nodes repel each other like magnets, and edges act as springs. Related things drift together and form clusters — so <b>structure emerges from relationships</b>, not from a layout anyone designed. A tight cluster is a working subsystem; look for the floating-UI cluster (<code>floatimg-buttons.html</code> + <code>floating-ui.md</code> + its skill) in your real map.</p>
<h3>Reading the map</h3>
<table>
<tr><th>Pattern</th><th>Meaning</th></tr>
<tr><td>Hub node (many thick edges)</td><td>A load-bearing component — many things depend on it</td></tr>
<tr><td>Large node</td><td>Frequently accessed (count = size)</td></tr>
<tr><td>Thick edge</td><td>Two things used together often (weight / use_count)</td></tr>
<tr><td>Island (no edges)</td><td>Orphan — unused file/skill: prune it or revive it</td></tr>
<tr><td>Red <span style="color:var(--rd)">✕</span></td><td>Failure marker — broken reference or failed item</td></tr>
<tr><td>Dense cyan bar on the scrubber</td><td>A busy period in your system's history</td></tr>
</table>
</section>
<section id="viewer"><h2><span class="n">05</span>Viewer controls</h2>
<table>
<tr><th>Control</th><th>What it does</th></tr>
<tr><td><b>Drag a node</b></td><td>Rearrange it — the physics re-settles around your hand</td></tr>
<tr><td><b>Cyan time-scrubber</b></td><td>Slide through history; density bars show activity per period; the graph rebuilds as of that moment</td></tr>
<tr><td><b>▶ Replay</b></td><td>Animates your system's history forward in time</td></tr>
<tr><td><b>Click a node</b></td><td>Stats panel: type, access count, created, connections</td></tr>
<tr><td><b>PNG export</b></td><td>Saves the current map as an image</td></tr>
</table>
</section>
<section id="export"><h2><span class="n">06</span>Export & the bake — why downloaded copies break</h2>
<p>Exported or previewed HTML runs in an <b>opaque-origin sandbox</b>: <code>localStorage</code>, <code>IndexedDB</code> and <code>window.modules</code> are <b>all blocked</b>. The 3-channel live loader dies instantly, and a plain copy shows “Embedded snapshot missing — re-export this file.”</p>
<p>The fix is to <b>bake</b>: embed the snapshot directly into the HTML — a <code>const EMBED={n:[…],e:[…],ts:"…"}</code> constant plus an <code>embed()</code> fallback at the end of the loader chain (edge indices remapped to real node ids). The file then renders <i>anywhere</i>, forever, with zero storage access.</p>
<div class="note">That is exactly why <code>memgraph.html</code> (45 KB, baked) works when you double-click it, while the 21.5 KB <code>memgraph-today.html</code> still needs the newOS4 origin. Same code — the difference is the snapshot inside.</div>
<div class="note warn"><b>This guide follows the same lesson:</b> fully self-contained — inline styles, inline demo, no CDN, no storage reads. It renders in the sandbox, in a download, anywhere. (And a good bake also hides the loading overlay once data lands, so the map doesn't sit behind “loading…” forever.)</div>
</section>
<section id="demo"><h2><span class="n">07</span>Try it — a miniature of the real thing</h2>
<p class="mut">A tiny force-directed graph of tonight's actual cast (files, skills, modules, tasks — and one failed <code>bake_out</code> that got wiped by a filesystem flush, wearing its red ✕). Drag nodes around; watch the springs re-settle. Same physics as the real viewer.</p>
<canvas id="demo"></canvas>
<div class="legend">
<span><span class="sw" style="background:#22d3ee"></span>file</span>
<span><span class="sw" style="background:#f59e0b"></span>skill</span>
<span><span class="sw" style="background:#a78bfa"></span>module</span>
<span><span class="sw" style="background:#34d399"></span>task</span>
<span><span class="sw" style="background:#94a3b8"></span>storage / system</span>
<span><span class="sw" style="background:#f87171"></span>failure ✕</span>
</div>
</section>
<section id="status"><h2><span class="n">08</span>Status tonight (2026-10-17)</h2>
<table>
<tr><th>File</th><th>Size</th><th>State</th></tr>
<tr><td><code>/memgraph.html</code></td><td>45,049 bytes</td><td class="ok">baked ✓ — renders standalone</td></tr>
<tr><td><code>/memgraph-today.html</code></td><td>21,545 bytes</td><td class="pend">bake pending — needs newOS4 origin (or a bake)</td></tr>
<tr><td><code>/memgraph-guide.html</code></td><td>this page</td><td class="ok">self-contained ✓ — zero external deps</td></tr>
</table>
<p class="mut">Live graph at time of writing: <b>228 nodes · 321 edges</b>. Most-accessed: floatimg-buttons.html (16×), floating-ui.md (6×).</p>
</section>
<footer>memgraph guide · generated 2026-10-17 by the newOS4 debug agent · system v4.6.26 · no external assets, no storage access — it practices what section 06 preaches.</footer>
</div>
<script>
(function(){
var cv=document.getElementById('demo'),X=cv.getContext('2d');
function fit(){cv.width=cv.clientWidth;cv.height=cv.clientHeight;}
window.addEventListener('resize',fit);fit();
var C={file:'#22d3ee',skill:'#f59e0b',module:'#a78bfa',task:'#34d399',sys:'#94a3b8'};
var ND=[
['floatimg-buttons.html','file'],['floating-ui.md','file'],['memgraph.html','file'],['memgraph-today.html','file'],
['memgraph-guide.html','file'],['bake-extract.js','file'],['bake-finalize.js','file'],
['memgraph-html-visualization','skill'],['debug-panel-and-logs','skill'],['system-maintenance','skill'],
['MemoryGraphModule','module'],['OrchestratorModule','module'],['FloatingModule','module'],
['task: bake memgraph-today','task'],['task: write memgraph guide','task'],['task: use agents','task'],
['VFS','sys'],['localStorage','sys'],['IndexedDB','sys'],['agents','sys'],
['bake_out (wiped)','fail']];
var ED=[[0,1,3],[0,12,2],[0,16,1],[2,10,3],[3,10,3],[3,13,2],[2,15,1],[4,14,3],[5,13,1],[6,13,1],[6,16,1],
[8,16,1],[9,11,1],[7,2,1],[7,3,1],[7,4,1],[10,17,1],[10,18,1],[10,19,2],[14,10,1],[4,16,1],[20,6,1],[20,13,1],
[13,11,1],[3,20,1],[1,7,1]];
var nodes=ND.map(function(d,i){var a=i/ND.length*6.283;return{l:d[0],t:d[1],x:cv.width/2+Math.cos(a)*130,y:cv.height/2+Math.sin(a)*80,vx:0,vy:0,r:7};});
var deg=[];for(var q=0;q<ND.length;q++)deg[q]=0;
ED.forEach(function(e){deg[e[0]]++;deg[e[1]]++;});
nodes.forEach(function(n,i){n.r=5.5+deg[i]*1.7;});
var drag=null;
function step(){
for(var i=0;i<nodes.length;i++)for(var j=i+1;j<nodes.length;j++){
var a=nodes[i],b=nodes[j],dx=b.x-a.x,dy=b.y-a.y,d2=dx*dx+dy*dy;
if(d2<4)d2=4;var d=Math.sqrt(d2),f=1100/d2;dx/=d;dy/=d;
a.vx-=dx*f;a.vy-=dy*f;b.vx+=dx*f;b.vy+=dy*f;}
ED.forEach(function(e){var a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.sqrt(dx*dx+dy*dy)||1;
var f=(d-95)*0.012*Math.min(e[2],3);dx/=d;dy/=d;
a.vx+=dx*f;a.vy+=dy*f;b.vx-=dx*f;b.vy-=dy*f;});
nodes.forEach(function(n){
if(n===drag)return;
n.vx+=(cv.width/2-n.x)*0.0016;n.vy+=(cv.height/2-n.y)*0.0016;
n.vx*=0.86;n.vy*=0.86;n.x+=n.vx;n.y+=n.vy;
if(n.x<24)n.x=24;if(n.x>cv.width-24)n.x=cv.width-24;
if(n.y<24)n.y=24;if(n.y>cv.height-24)n.y=cv.height-24;});
}
function draw(){
X.clearRect(0,0,cv.width,cv.height);
ED.forEach(function(e){var a=nodes[e[0]],b=nodes[e[1]];
X.strokeStyle='rgba(110,160,190,.30)';X.lineWidth=0.8+(e[2]||1)*0.6;
X.beginPath();X.moveTo(a.x,a.y);X.lineTo(b.x,b.y);X.stroke();});
nodes.forEach(function(n){
if(n.t==='fail'){X.fillStyle='#2a1313';X.strokeStyle='#f87171';}
else{X.fillStyle=C[n.t];X.strokeStyle='rgba(255,255,255,.18)';}
X.beginPath();X.arc(n.x,n.y,n.r,0,6.284);X.fill();X.lineWidth=1;X.stroke();
if(n.t==='fail'){X.strokeStyle='#f87171';X.lineWidth=2;var k=n.r*0.62;
X.beginPath();X.moveTo(n.x-k,n.y-k);X.lineTo(n.x+k,n.y+k);X.moveTo(n.x+k,n.y-k);X.lineTo(n.x-k,n.y+k);X.stroke();}
X.fillStyle='rgba(215,232,242,.8)';X.font='10px ui-monospace,Consolas,monospace';X.textAlign='center';
X.fillText(n.l,n.x,n.y+n.r+13);});
}
function pt(e){var r=cv.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top};}
cv.addEventListener('pointerdown',function(e){var p=pt(e),best=null,bd=484;
nodes.forEach(function(n){var d=(n.x-p.x)*(n.x-p.x)+(n.y-p.y)*(n.y-p.y);if(d<bd){bd=d;best=n;}});
if(best){drag=best;best.vx=best.vy=0;cv.setPointerCapture(e.pointerId);cv.style.cursor='grabbing';}});
cv.addEventListener('pointermove',function(e){if(!drag)return;var p=pt(e);drag.x=p.x;drag.y=p.y;drag.vx=drag.vy=0;});
cv.addEventListener('pointerup',function(){drag=null;cv.style.cursor='grab';});
(function loop(){step();draw();requestAnimationFrame(loop);})();
})();
</script></body></html>
|