Publish the measured Flint and Qwen explorer

#1
by alphabell-research - opened
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ cover.png filter=lfs diff=lfs merge=lfs -text
37
+ preview.png filter=lfs diff=lfs merge=lfs -text
.github/workflows/checks.yml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Observatory checks
2
+ on: [push, pull_request]
3
+ permissions:
4
+ contents: read
5
+ jobs:
6
+ captures:
7
+ runs-on: ubuntu-24.04
8
+ timeout-minutes: 10
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: actions/setup-node@v4
12
+ with:
13
+ node-version: '22'
14
+ - run: npm test
15
+ - run: node --check app.js && node --check detail.js
16
+ browser:
17
+ runs-on: ubuntu-24.04
18
+ timeout-minutes: 15
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+ - run: python -m pip install -r requirements-dev.txt
25
+ - name: Exercise both real captures and every primary flow
26
+ run: |
27
+ python -m http.server 8000 --bind 127.0.0.1 > /tmp/observatory-http.log 2>&1 &
28
+ http_pid=$!
29
+ trap 'kill "$http_pid"' EXIT
30
+ browser_path="$(command -v google-chrome || command -v chromium)"
31
+ "$browser_path" --version
32
+ python verify.py --base http://127.0.0.1:8000 --chromium "$browser_path"
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ __pycache__/
2
+ .venv/
3
+ node_modules/
4
+ reports/
5
+ .DS_Store
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 alphaBell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
NOTICE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Model Observatory
2
+ Copyright 2026 alphaBell. Viewer code is licensed under MIT.
3
+
4
+ Model configuration references:
5
+ RecursiveSI/flint, Recursive Superintelligence, Inc.
6
+ https://huggingface.co/RecursiveSI/flint
7
+ Qwen/Qwen3.8-27B, Qwen Team
8
+ https://huggingface.co/Qwen/Qwen3.8-27B
9
+ The publishers distribute these models under Apache License 2.0:
10
+ https://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Configurations record architectural facts. The Qwen configuration describes
13
+ its text decoder; the source model also includes other components.
14
+ Bundled measured activation captures are published by alphaBell for reuse
15
+ with this viewer. No model weights are included.
16
+
17
+ Capture engine reference: llama.cpp, MIT License
18
+ https://github.com/ggml-org/llama.cpp
19
+ No llama.cpp source or executable is included in this static viewer.
README.md CHANGED
@@ -1,10 +1,79 @@
1
  ---
2
  title: Model Observatory
3
- emoji: 📈
4
- colorFrom: yellow
5
- colorTo: yellow
6
  sdk: static
7
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Model Observatory
3
+ emoji: 🔬
4
+ colorFrom: green
5
+ colorTo: gray
6
  sdk: static
7
+ app_file: index.html
8
+ pinned: true
9
+ license: mit
10
+ short_description: "Real Flint and Qwen Q8 captures, replayed token by token"
11
+ thumbnail: https://huggingface.co/spaces/alphabell/Model-Observatory/resolve/main/cover.png
12
+ models:
13
+ - RecursiveSI/flint
14
+ - Qwen/Qwen3.8-27B
15
+ tags:
16
+ - interpretability
17
+ - visualization
18
+ - mixture-of-experts
19
+ - attention
20
+ - recurrent-memory
21
+ - qwen
22
+ - flint
23
+ - educational
24
  ---
25
 
26
+ # Model Observatory
27
+
28
+ **What changes inside a language model as it writes its next token?**
29
+
30
+ Explore two different architectures with real Q8_0 tensor captures: Flint's sparse expert routing and Qwen's recurrent memory. Open a block, head or expert, then step through the tokens that used it.
31
+
32
+ [**Open the explorer**](https://huggingface.co/spaces/alphabell/Model-Observatory) · [Qwen view](https://alphabell-model-observatory.static.hf.space/?model=qwen) · [Source](https://huggingface.co/spaces/alphabell/Model-Observatory/tree/main) · [alphaBell](https://alphabell.com)
33
+
34
+ ![Model Observatory showing Flint attention heads and selected experts for one captured token.](preview.png)
35
+
36
+ ## Try it
37
+
38
+ 1. Open **Flint**. Choose a token, then click one of the six selected experts in layer 12. Its timeline shows when the router selected it.
39
+ 2. Switch to **Qwen**. Open a recurrent head in layer 0 to inspect its write gate, retention and state RMS. Layer 3 uses full attention instead.
40
+ 3. Use **Token history** to compare head-output magnitudes across the answer. Open a block for fullscreen inspection, or slow replay to one token every eight seconds.
41
+ 4. Export the complete trace or import a compatible capture JSON. Files stay in your browser tab. **Share view** links to a model, layer and token in the bundled example; it does not upload imported files.
42
+
43
+ The two examples use the same prompt, “Explain why the sky is blue in two sentences.” Flint contains 59 output-token frames; Qwen contains 44. Captures include the original sampling settings, token bytes, timings and architecture. Measurements retain their original numeric values. Public run identifiers replace internal identifiers.
44
+
45
+ ## Two architectures
46
+
47
+ | | Recursive Flint | Qwen3.8-27B text decoder |
48
+ | --- | --- | --- |
49
+ | Decoder blocks | 49 | 64 |
50
+ | Attention | 14 full, 35 sliding | 48 Gated DeltaNet, 16 full |
51
+ | Heads | 32 query, 4 KV | Recurrent: 48 value, 16 key. Full: 24 query, 4 KV |
52
+ | Feed-forward | First 2 blocks dense; then top 6 of 256 routed experts plus a shared expert | Dense in every block |
53
+ | Capture precision | Q8_0 | Q8_0 |
54
+
55
+ ## Reading the measurements
56
+
57
+ Head brightness is output RMS before the output projection. Every head executes; brightness is a magnitude, not an on/off signal. The structure view scales brightness to the current frame's 95th percentile. Token history uses one scale over the entire trace. Use the exact displayed values to compare frames or models.
58
+
59
+ Expert selection and normalized routing weights are directly captured. Individual routed-expert output vectors are not retained; expert views show routing and aggregate routed output. Full/sliding attention retains its eight strongest token positions, rather than the full attention matrix. Flint has a learned attention sink; its recorded entropy is the token-position contribution.
60
+
61
+ Qwen's recurrent heads update memory instead of producing a token-position softmax. Their views show write gates, retention and state RMS. The Qwen capture covers its text decoder, excluding vision and MTP.
62
+
63
+ Each frame is the forward pass that **predicts** the selected output token. The first frame uses the last prompt token; subsequent frames use the preceding generated token. Magnitudes and routing describe these runs. They do not establish causal explanations or model quality rankings.
64
+
65
+ ## Captures and provenance
66
+
67
+ Both examples were measured with an instrumented llama.cpp evaluation callback at commit `74686f08`, with Flash Attention disabled. Capture uses native tensor strides and supports reshaped routing weights. The saved metadata records CPU execution, 16 threads and a 2048-token context. Playback speed changes presentation, independently of the original capture timings.
68
+
69
+ The public Space is a static capture explorer. It does not generate new answers. A separate instrumented capture engine is required to produce additional traces. [Trace format and compatibility](TRACE-FORMAT.md) explains the accepted exports; ordinary chat API responses do not contain these measurements.
70
+
71
+ [Source pins](sources.json) identify the model configurations checked for this release. [Capture manifest](traces/index.json) records SHA-256 checksums of compressed files and decoded JSON. The browser verifies both before loading an example. Local imports are checked for model identity, architecture, dimensions and valid measurements before replacing the current trace.
72
+
73
+ ## Run locally
74
+
75
+ Serve this directory over HTTP, for example with `python3 -m http.server 8000`, then open `http://localhost:8000`. There is no build step, inference service, account or API key. The viewer uses browser gzip streams and Web Crypto, available in current Chrome, Firefox and Safari over HTTPS or localhost.
76
+
77
+ Run `npm test` for trace and release checks. For interaction checks, install `requirements-dev.txt`, install Playwright Chromium, serve the directory, and run `python verify.py --base http://localhost:8000`. Browser checks also accept `--chromium /path/to/chromium`.
78
+
79
+ Built by **alphaBell**. Model Observatory is an independent project. Model configurations and names belong to their respective publishers. See [NOTICE](NOTICE) and [LICENSE](LICENSE).
TRACE-FORMAT.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Importing a capture
2
+
3
+ Use **Export trace** to download a complete working example. The same JSON imports into this viewer. Import reads the file locally and never sends its contents to a server. Closing the tab discards imported state.
4
+
5
+ Supported schemas are `flint.trace.v1` for Flint and `model.trace.v1` for Flint or Qwen. Legacy Flint exports without `model` metadata remain supported. Both registered checkpoints use Q8_0. A different architecture or quantization requires a separate registry entry and compatible measurements.
6
+
7
+ A trace contains:
8
+
9
+ | Field | Contents |
10
+ | --- | --- |
11
+ | `schema` | Supported schema identifier |
12
+ | `model` | Model identity and quantization; `id` is `flint` or `qwen` |
13
+ | `architecture` | Text-decoder configuration matching `models.json` |
14
+ | `prompt` | Original prompt, up to 4000 characters |
15
+ | `settings` | Recorded output limit, temperature, seed and reasoning flag |
16
+ | `start.tokens` | Decoded input-token pieces, including chat-template tokens |
17
+ | `frames` | 1 to 256 output-token frames, in generation order |
18
+
19
+ Each frame records `text`, `token_id`, optional raw UTF-8 `token_bytes`, `input_position`, `duration`, `elapsed`, and one entry per decoder block in `layers`. `input_position` begins at `start.tokens.length - 1` and increases by one. It identifies the input that predicted this frame's output token. Capture context is limited to 2048 positions.
20
+
21
+ Every layer includes finite, nonnegative `heads`, `ffn` and `residual` RMS measurements. Head count follows the layer type. Flint MoE layers add six unique `experts`, six normalized `weights`, and `shared` and `routed` output RMS. Its first two layers are dense.
22
+
23
+ Attention layers include one `attention` entry per head, with `top` position/probability pairs, `entropy`, and Flint's `sink` probability. Only the strongest eight positions are retained. Recurrent layers instead include `write_gate`, `retention`, and `state_rms` arrays per value head.
24
+
25
+ The viewer checks all frames and relevant architecture dimensions before changing the loaded trace. It accepts stopped captures containing valid complete frames. It rejects empty captures, malformed JSON, inconsistent model identity and invalid measurement dimensions. Files larger than 160 MB are rejected before parsing.
26
+
27
+ A compatible exporter must record actual tensors from an instrumented model execution. An ordinary text completion does not supply attention, routing or recurrent-state measurements. The bundled captures provide concrete, downloadable examples of the complete format.
app.js ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+ const $=id=>document.getElementById(id);
3
+ const S={models:[],model:null,config:null,frames:[],frame:-1,layer:12,head:0,expert:null,live:true,running:false,requesting:false,switching:false,partial:[],activeLayer:-1,id:null,start:null,view:'structure',output:'',decoder:new TextDecoder(),timer:null,speed:500,slowOnRun:false,stream:null,trace:null,geometry:null,loadingTrace:false,detail:null};
4
+ const snapshots=new Map();
5
+ const pad=n=>String(n).padStart(2,'0');
6
+ const fmt=n=>Number.isFinite(n)?n.toFixed(3):'unmeasured';
7
+ const pct=n=>(100*n).toFixed(1)+'%';
8
+ const layerCount=()=>S.config.num_hidden_layers;
9
+ const isLinear=(l=S.layer)=>S.config.layer_types[l]==='linear_attention';
10
+ const isMoe=(l=S.layer)=>Boolean(S.config.num_experts)&&!(S.config.mlp_only_layers||[]).includes(l)&&l>=(S.config.first_k_dense_replace||0);
11
+ const headCount=(l=S.layer)=>isLinear(l)?S.config.linear_num_value_heads:S.config.num_attention_heads;
12
+ const headDimension=(l=S.layer)=>isLinear(l)?S.config.linear_value_head_dim:S.config.head_dim;
13
+ const keyHeadCount=(l=S.layer)=>isLinear(l)?S.config.linear_num_key_heads:S.config.num_key_value_heads;
14
+ const keyHead=(h=S.head,l=S.layer)=>isLinear(l)?h%keyHeadCount(l):Math.floor(h/(headCount(l)/keyHeadCount(l)));
15
+ function attentionLabel(l=S.layer){if(isLinear(l))return 'Recurrent linear attention';if(S.config.layer_types[l]==='sliding_attention')return 'Sliding attention · '+S.config.sliding_window;return (S.config.no_rope_layer_indices||[]).includes(l)?'Full attention · no RoPE':'Full attention · partial RoPE';}
16
+ let toastTimer,drawQueued=false;
17
+ function toast(message){$('toast').textContent=message;$('toast').hidden=false;clearTimeout(toastTimer);toastTimer=setTimeout(()=>$('toast').hidden=true,5000);}
18
+
19
+
20
+
21
+ function current(){return S.live&&S.running&&S.partial.length?S.partial:S.frames[S.frame]?.layers||[];}
22
+ function colour(value,max){const t=Math.max(0,Math.min(1,value/(max||1)));const a=[236,242,224],b=[26,113,83];return `rgb(${a.map((v,i)=>Math.round(v+(b[i]-v)*Math.pow(t,.7))).join(',')})`;}
23
+ function scaleFor(layers){const v=layers.flatMap(l=>l?.heads||[]).filter(Number.isFinite).sort((a,b)=>a-b);return v[Math.floor(v.length*.95)]||1;}
24
+ function update(){if(!S.config)return;requestDraw();renderInspector();renderPlayback();if(typeof renderDetail==='function')renderDetail();$('modelSelect').disabled=S.running||S.requesting||S.loadingTrace||S.switching;$('modelSelect').title=S.running?'Stop generation to switch models.':'Choose a model to inspect.';}
25
+ function requestDraw(){if(drawQueued)return;drawQueued=true;requestAnimationFrame(()=>{drawQueued=false;if(S.config)draw();});}
26
+ function draw(){
27
+ const canvas=$('modelCanvas'),box=canvas.parentElement.getBoundingClientRect(),w=box.width,h=box.height,dpr=window.devicePixelRatio||1;
28
+ if(canvas.width!==Math.round(w*dpr)||canvas.height!==Math.round(h*dpr)){canvas.width=w*dpr;canvas.height=h*dpr;}
29
+ const c=canvas.getContext('2d');c.setTransform(dpr,0,0,dpr,0,0);c.clearRect(0,0,w,h);
30
+ const layers=current(),max=scaleFor(layers),top=71,bottom=h-38,rh=(bottom-top)/layerCount();c.textBaseline='middle';c.font='9px "IBM Plex Mono",monospace';
31
+ if(S.view==='history'){
32
+ const left=43,right=w-18,cw=(right-left)/Math.max(1,S.frames.length),hm=scaleFor(S.frames.flatMap(f=>f.layers||[]));
33
+ c.fillStyle='#6e8361';c.textAlign='center';c.fillText('HEAD OUTPUT MAGNITUDE OVER TOKENS',w/2,26);
34
+ if(!S.frames.length){c.fillStyle='#a3ae97';c.fillText('Open a measured trace to inspect its token history.',w/2,h/2);}
35
+ for(let l=0;l<layerCount();l++){const y=top+l*rh;c.fillStyle='#91a088';c.textAlign='right';c.font='8px "IBM Plex Mono",monospace';c.fillText(pad(l),left-9,y+rh/2);for(let t=0;t<S.frames.length;t++){const vals=S.frames[t].layers[l]?.heads,avg=vals?.reduce((a,b)=>a+b,0)/headCount(l);c.fillStyle=Number.isFinite(avg)?colour(avg,hm):'#eff2e8';c.fillRect(left+t*cw,y+1,Math.max(1,cw-1),rh-2);}}
36
+ if(S.frame>=0){c.strokeStyle='#31583a';c.lineWidth=1.3;c.strokeRect(left+S.frame*cw,top,Math.max(1,cw),rh*layerCount());}
37
+ c.textAlign='left';c.fillStyle='#93a087';c.fillText('Layer ↓',left,top-14);c.textAlign='right';c.fillText('Generated token →',right,top-14);S.geometry={history:true,left,right,top,rh,cw,w,h};return;
38
+ }
39
+ const margin=w<410?7:17,left=margin+32,right=w-margin,usable=right-left-54,headW=usable*.43,expW=usable*.57,hx=left+12,ex=hx+headW+14,sx=right-9;
40
+ c.fillStyle='#eff3e9';c.strokeStyle='#e1e8da';c.lineWidth=1;roundRect(c,w/2-79,11,158,25,5);c.fill();c.stroke();c.fillStyle='#6d815e';c.textAlign='center';c.font='8px "IBM Plex Mono",monospace';c.fillText('TOKEN → EMBEDDING · '+S.config.hidden_size,w/2,24);
41
+ c.strokeStyle='#cad6bf';c.beginPath();c.moveTo(w/2,37);c.lineTo(w/2,44);c.stroke();
42
+ c.textAlign='left';c.fillStyle='#8d9c81';c.fillText('LAYER',margin,56);c.fillText(S.model.id==='qwen'?'48 RECURRENT / 24 FULL':headCount()+' ATTENTION HEADS',hx,56);c.fillText(S.config.num_experts?S.config.num_experts+' ROUTED EXPERTS':'DENSE FEED-FORWARD',ex,56);if(S.config.num_experts){c.textAlign='center';c.fillText('S',sx,56);}
43
+ for(let l=0;l<layerCount();l++){
44
+ const y=top+l*rh,cy=y+rh/2,data=layers[l],selected=l===S.layer,full=S.config.layer_types[l]==='full_attention',count=headCount(l);
45
+ if(selected){c.fillStyle='#edf3e5';roundRect(c,margin-3,y,w-2*margin+6,rh,2);c.fill();}
46
+ if(S.running&&S.live&&S.activeLayer===l){c.fillStyle='#cee6af';roundRect(c,margin-3,y,w-2*margin+6,rh,2);c.fill();}
47
+ c.fillStyle=full?'#7095a2':isLinear(l)?'#8fa99d':'#bbcbb0';c.fillRect(left-1,y+rh*.2,2,rh*.6);c.fillStyle=selected?'#3e643c':'#98a58c';c.textAlign='left';c.font='8px "IBM Plex Mono",monospace';c.fillText(pad(l),margin,cy);
48
+ for(let head=0;head<count;head++){const hw=headW/count;c.fillStyle=data?.heads?colour(data.heads[head],max):'#e5ebdf';roundRect(c,hx+head*hw,y+rh*.22,Math.max(1,hw-1),rh*.56,.7);c.fill();if(selected&&head===S.head){c.strokeStyle='#214d36';c.lineWidth=.9;c.strokeRect(hx+head*hw-.5,y+rh*.17,hw-.3,rh*.66);}}
49
+ c.strokeStyle='#d7e2cc';c.beginPath();c.moveTo(hx+headW+2,cy);c.lineTo(ex-3,cy);c.stroke();
50
+ if(!isMoe(l)){c.fillStyle=Number.isFinite(data?.ffn)?colour(data.ffn,max):data?'#c4dab5':'#e7ecdf';roundRect(c,ex,y+rh*.18,expW,rh*.64,1);c.fill();c.fillStyle=Number.isFinite(data?.ffn)&&data.ffn/max>.6?'#f4f9eb':'#8a9b7d';c.font='7px "IBM Plex Mono",monospace';c.fillText('DENSE FFN · '+S.config.intermediate_size,ex+5,cy);}
51
+ else{const ew=expW/64,eh=rh*.8/4,ids=data?.experts||[];for(let expert=0;expert<S.config.num_experts;expert++){const rank=ids.indexOf(expert);c.fillStyle=rank>=0?colour(data.weights?.[rank]||.17,.27):'#e7ecdf';c.fillRect(ex+(expert%64)*ew,y+rh*.1+Math.floor(expert/64)*eh,Math.max(1,ew-.7),Math.max(.8,eh-.5));}c.fillStyle=data?.shared!==undefined?colour(data.shared,max):'#e6ecdd';roundRect(c,sx-3,y+rh*.22,6,rh*.56,1);c.fill();}
52
+ }
53
+ c.fillStyle='#eef3e6';c.strokeStyle='#e0e9d4';roundRect(c,w/2-85,h-27,170,22,4);c.fill();c.stroke();c.fillStyle='#7c916a';c.textAlign='center';c.font='8px "IBM Plex Mono",monospace';c.fillText('RMSNORM → LM HEAD → NEXT TOKEN',w/2,h-16);S.geometry={history:false,margin,left,hx,ex,sx,headW,expW,top,rh,w,h};
54
+ }
55
+ function roundRect(c,x,y,w,h,r){c.beginPath();c.roundRect(x,y,w,h,r);}
56
+ function ensureInspectorControls(){
57
+ if($('headGrid').children.length!==headCount()){$('headGrid').replaceChildren();for(let i=0;i<headCount();i++){const b=document.createElement('button');b.className='head';b.textContent=pad(i);b.ariaLabel='Inspect '+(isLinear()?'linear value':'attention')+' head '+i;b.onclick=()=>openDetail('head',i);$('headGrid').append(b);}}
58
+ if($('expertGrid').children.length!==(S.config.num_experts||0)){$('expertGrid').replaceChildren();for(let i=0;i<(S.config.num_experts||0);i++){const b=document.createElement('button');b.className='expert';b.ariaLabel='Expert '+i;b.onclick=()=>openDetail('expert',i);$('expertGrid').append(b);}}
59
+ }
60
+ function renderInspector(){
61
+ if(!S.config)return;ensureInspectorControls();S.head=Math.min(S.head,headCount()-1);
62
+ const l=S.layer,data=current()[l],dense=!isMoe(),linear=isLinear(),max=scaleFor(current());
63
+ $('layerNumber').textContent=pad(l);$('layerType').textContent=linear?'Linear':S.config.layer_types[l]==='full_attention'?'Full attention':'Sliding · '+S.config.sliding_window;$('flowAttention').textContent=attentionLabel();$('flowMlp').textContent=dense?'Dense FFN · '+S.config.intermediate_size:'Router → '+S.config.num_experts_per_tok+' + shared';$('prevLayer').disabled=l===0;$('nextLayer').disabled=l===layerCount()-1;
64
+ $('headGridTitle').textContent=linear?'Recurrent value heads':'Attention heads';$('headGridCount').textContent=linear?headCount()+' V · '+keyHeadCount()+' K':headCount()+' Q · '+keyHeadCount()+' KV';
65
+ for(let i=0;i<headCount();i++){const b=$('headGrid').children[i];b.classList.toggle('selected',i===S.head);b.style.background=data?.heads?colour(data.heads[i],max):'';b.style.color=data?.heads&&data.heads[i]/max>.6?'#f4f9eb':'#7d926e';b.title=`Head ${i} · ${linear?'key':'KV'} head ${keyHead(i)}${data?.heads?' · output RMS '+fmt(data.heads[i]):''}`;}
66
+ $('headLabel').textContent=`${linear?'Value head':'Head'} ${pad(S.head)} · ${linear?'K':'KV'} ${keyHead()}`;$('headValue').textContent=data?.heads?fmt(data.heads[S.head])+' RMS':'Awaiting trace';
67
+ $('expertTitle').textContent=dense?'Dense feed-forward':'Expert routing';$('expertCount').textContent=dense?S.config.intermediate_size+' width':(data?.experts?.length||S.config.num_experts_per_tok)+' of '+S.config.num_experts;$('expertGrid').hidden=dense;$('sharedExpert').hidden=dense;
68
+ for(let i=0;i<(S.config.num_experts||0);i++){const b=$('expertGrid').children[i],index=data?.experts?.indexOf(i)??-1;b.classList.toggle('active',index>=0);b.classList.toggle('focused',S.expert===i);b.title=`Expert ${i}${index>=0?' · routing weight '+pct(data.weights[index]):' · not selected'}`;}
69
+ $('expertList').replaceChildren();
70
+ if(dense){const b=document.createElement('button');b.className='dense-inspect';b.textContent=Number.isFinite(data?.ffn)?'Output '+fmt(data.ffn)+' RMS ↗':'Inspect dense feed-forward ↗';b.onclick=()=>openDetail('ffn');$('expertList').append(b);}
71
+ else if(data?.experts){data.experts.forEach((id,i)=>{const b=document.createElement('button');b.className='expert-chip';b.title='Open expert '+id+' fullscreen';b.onclick=()=>openDetail('expert',id);const label=document.createElement('b');label.textContent='E'+String(id).padStart(3,'0');b.append(label,document.createTextNode(pct(data.weights[i])));$('expertList').append(b);});}
72
+ else{$('expertList').innerHTML='<span class="muted">Run a prompt to see selected experts.</span>';}
73
+ $('sharedValue').textContent=data?.shared!==undefined?fmt(data.shared)+' RMS':'Always active';$('sharedExpert').querySelector('i').style.background=data?.shared!==undefined?'#79ad56':'';renderAttention(data);
74
+ }
75
+ function recurrentReading(data,dest){
76
+ for(const [label,value]of [['Write gate',data?.write_gate?.[S.head]],['Memory retention',data?.retention?.[S.head]],['State RMS',data?.state_rms?.[S.head]]]){const row=document.createElement('div');row.className='recurrent-reading';const name=document.createElement('span');name.textContent=label;const v=document.createElement('strong');v.textContent=Number.isFinite(value)?label==='State RMS'?fmt(value):pct(value):'Awaiting trace';row.append(name,v);dest.append(row);}
77
+ const note=document.createElement('p');note.className='recurrent-note';note.textContent='This head updates a recurrent memory instead of a token-position attention map.';dest.append(note);
78
+ }
79
+ function renderAttention(data){
80
+ const dest=$('attentionList');dest.replaceChildren();$('attentionTitle').textContent=isLinear()?'Recurrent memory':'Where this head attends';$('attentionCount').textContent=isLinear()?'Gated DeltaNet':'top 8 positions';
81
+ if(isLinear()){recurrentReading(data,dest);return;}
82
+ const a=data?.attention?.[S.head];if(!a){const s=document.createElement('span');s.className='muted';s.textContent='Select a token to inspect its attention.';dest.append(s);return;}
83
+ const tokens=[...(S.start?.tokens||[]),...S.frames.map(f=>f.text)];
84
+ for(const [pos,weight]of a.top){const row=document.createElement('div');row.className='attention-row';const p=document.createElement('span');p.className='pos';p.textContent=String(pos);const word=document.createElement('span');word.className='attention-word';word.style.setProperty('--weight',pct(weight));word.textContent=(tokens[pos]??'#'+pos).replace(/\n/g,'↵');word.title=tokens[pos]||'';const v=document.createElement('span');v.className='weight';v.textContent=pct(weight);row.append(p,word,v);dest.append(row);}
85
+ const note=document.createElement('div');note.className='sink-note';note.textContent=(S.model.learned_sink?'Learned sink '+pct(a.sink)+' · ':'')+'Token entropy '+fmt(a.entropy)+' nats';dest.append(note);
86
+ }
87
+ function renderPlayback(){
88
+ const n=S.frames.length;$('frameLabel').textContent=`TOKEN ${String(Math.max(0,S.frame+1)).padStart(3,'0')} / ${String(n).padStart(3,'0')}`;$('scrubber').disabled=!n;$('scrubber').max=Math.max(0,n-1);$('scrubber').value=Math.max(0,S.frame);$('stepBack').disabled=S.frame<=0;$('stepForward').disabled=S.frame>=n-1;$('playButton').disabled=!n;$('exportButton').disabled=!n||S.running;
89
+ $('liveButton').classList.toggle('live-selected',S.live);$('playButton').textContent=S.timer?'Ⅱ':'▶';$('playButton').ariaLabel=S.timer?'Pause trace':'Play trace';
90
+ $('playSpeed').value=String(S.speed);
91
+ const strip=$('tokenStrip');if(n&&strip.children[0]?.className==='muted')strip.replaceChildren();
92
+ for(let i=strip.children.length;i<n;i++){const b=document.createElement('button');b.className='token';b.dataset.index=i;b.textContent=S.frames[i].text.replace(/\n/g,'↵')||'∅';b.title=`Output token ${i+1} · id ${S.frames[i].token_id} · ${fmt(S.frames[i].duration)} seconds`;b.onclick=()=>selectFrame(i);strip.append(b);}
93
+ for(const child of strip.children)child.classList.toggle('selected',Number(child.dataset.index)===S.frame);
94
+ $('tokenCount').textContent=n+' tokens';
95
+ if(S.frames[S.frame]){const f=S.frames[S.frame];$('captureLabel').textContent=`Measured frame ${S.frame+1} · input position ${f.input_position}`;}
96
+ }
97
+ function pausePlayback(){clearTimeout(S.timer);S.timer=null;}
98
+ function selectFrame(i,follow=false,playing=false){if(!playing)pausePlayback();S.live=follow;S.frame=Math.min(S.frames.length-1,Math.max(0,i));S.partial=[];S.activeLayer=-1;update();}
99
+ function playbackTick(){
100
+ if(S.frame<S.frames.length-1)selectFrame(S.frame+1,false,true);
101
+ else if(!S.running){pausePlayback();update();return;}
102
+ S.timer=setTimeout(playbackTick,S.speed);
103
+ }
104
+ function startPlayback(rewind=true){pausePlayback();S.live=false;S.partial=[];S.activeLayer=-1;if(rewind&&S.frame>=S.frames.length-1&&!S.running)S.frame=0;S.timer=setTimeout(playbackTick,S.speed);update();}
105
+ function togglePlayback(){if(S.timer){pausePlayback();update();}else if(S.frames.length)startPlayback();}
106
+ function changeSpeed(value){const wasPlaying=Boolean(S.timer),wasLive=S.live;S.speed=Number(value);S.slowOnRun=true;if(wasPlaying||(wasLive&&(S.frames.length||S.running)))startPlayback(false);else{S.live=false;update();}}
107
+ function selectLayer(l){S.layer=Math.max(0,Math.min(layerCount()-1,l));if(S.detail!=='expert')S.expert=null;if(!isMoe()&&(S.detail==='expert'||S.detail==='shared'))S.detail='ffn';if(isMoe()&&S.detail==='ffn')S.detail='block';S.head=Math.min(S.head,headCount()-1);update();}
108
+ function reset(){pausePlayback();S.frames=[];S.frame=-1;S.partial=[];S.output='';S.decoder=new TextDecoder();S.start=null;S.trace=null;S.activeLayer=-1;$('terminal').textContent='';$('tokenStrip').innerHTML='<span class="muted">Waiting for the first generated token.</span>';$('timing').textContent='Processing prompt';update();}
109
+ function renderTerminal(){const terminal=$('terminal'),nearBottom=terminal.scrollHeight-terminal.scrollTop-terminal.clientHeight<60;terminal.textContent=S.output;if(S.running){const cursor=document.createElement('span');cursor.className='cursor';cursor.textContent='▌';terminal.append(cursor);}if(nearBottom)terminal.scrollTop=terminal.scrollHeight;}
110
+ function renderIdentity(){
111
+ $('modelSelect').value=S.model.id;$('modelEyebrow').textContent=S.model.title.toUpperCase()+' · '+S.model.family.toUpperCase();$('quantization').textContent=S.model.quantization;$('promptLabel').textContent='Prompt '+S.model.short_name;
112
+ document.title=S.model.short_name+' | Model Observatory';$('modelCanvas').ariaLabel=S.model.title+' architecture: '+layerCount()+' layers. Click a block, head or feed-forward branch to inspect it.';
113
+ $('modelStats').replaceChildren();for(const [value,secondary,label]of S.model.stats){const item=document.createElement('div'),strong=document.createElement('strong'),caption=document.createElement('span');strong.textContent=value;if(secondary){const small=document.createElement('small');small.textContent=' / '+secondary;strong.append(small);}caption.textContent=label;item.append(strong,caption);$('modelStats').append(item);}
114
+ $('legendSecondary').textContent=S.config.layer_types.includes('linear_attention')?'Linear attention':'Sliding window';$('legendSecondarySwatch').className='swatch '+(S.config.layer_types.includes('linear_attention')?'linear':'sliding');$('legendActivation').textContent=S.config.num_experts?'Selected expert':'Dense FFN output';
115
+ $('aboutContent').replaceChildren();const paragraphs=[
116
+ S.model.title+' has '+layerCount()+' decoder blocks, hidden width '+S.config.hidden_size+' and a '+S.model.quantization+' tracing checkpoint. Head brightness is measured output RMS before the output projection. The colour scale uses the 95th percentile of the current frame; compare exact values across frames.',
117
+ S.config.num_experts?'The router chooses '+S.config.num_experts_per_tok+' of '+S.config.num_experts+' experts in each MoE block, plus one shared expert. Blocks '+S.config.mlp_only_layers.join(' and ')+' use dense feed-forward networks. Every attention head executes.':S.config.layer_types.filter(t=>t==='linear_attention').length+' blocks use Gated DeltaNet with '+S.config.linear_num_value_heads+' value heads and '+S.config.linear_num_key_heads+' key heads. They update recurrent memory through measured write and retention gates. The other '+S.config.layer_types.filter(t=>t==='full_attention').length+' blocks use full attention with '+S.config.num_attention_heads+' query heads and '+S.config.num_key_value_heads+' KV heads. All blocks use dense feed-forward width '+S.config.intermediate_size+'.',
118
+ 'Click any block or head for fullscreen inspection. Full-attention heads expose their strongest token positions. Recurrent heads expose write gates, memory retention and state RMS. A frame records the forward pass that predicts the selected output token.',
119
+ 'These are recorded Q8_0 tensor captures, replayed locally in your browser. Step, scrub or pause to inspect a token. The speed changes playback only. Jump to end selects the final captured token.',
120
+ 'The public Space replays saved captures; it does not run new prompts. Import a compatible trace JSON to inspect your own capture. Imported files stay in this tab and are never uploaded. Selecting another model preserves your current trace and selected token.'
121
+ ];for(const text of paragraphs){const p=document.createElement('p');p.textContent=text;$('aboutContent').append(p);}$('aboutSource').href=S.model.source_url;
122
+ }
123
+
124
+
125
+ function cacheModel(){if(!S.model)return;snapshots.set(S.model.id,{frames:S.frames,frame:S.frame,id:S.id,start:S.start,trace:S.trace,output:S.output,prompt:$('prompt').value,settings:null});}
126
+ function applyModel(model,restore=true){
127
+ if(S.model&&S.model.id!==model.id)cacheModel();if($('detailDialog').open)$('detailDialog').close();S.detail=null;if(typeof detailLayout!=='undefined')detailLayout='';
128
+ S.model=model;S.config=model.architecture;S.layer=model.id==='flint'?12:0;S.head=0;S.expert=null;S.id=null;S.live=true;reset();renderIdentity();
129
+ const saved=restore?snapshots.get(model.id):null;if(saved){Object.assign(S,{frames:saved.frames,frame:saved.frame,id:saved.id,start:saved.start,trace:saved.trace,output:saved.output,live:false});$('prompt').value=saved.prompt;renderTerminal();$('timing').textContent=S.frames.length+' tokens · recorded trace';}
130
+ else{$('terminal').textContent=model.short_name.toLowerCase()+' > open a measured trace';$('captureLabel').textContent='Structure ready · loading measured trace';$('timing').textContent='Recorded Q8_0 capture';}
131
+ const url=new URL(location.href);url.searchParams.set('model',model.id);history.replaceState({},'',url);update();
132
+ }
133
+ async function switchModel(id){
134
+ if(id===S.model.id||S.loadingTrace||S.switching)return;
135
+ const model=S.models.find(m=>m.id===id);if(!model)return;
136
+ S.switching=true;applyModel(model);update();
137
+ try{await loadHistory();if(!S.frames.length)await openExample(id);else renderCapture(S.trace);}catch(e){captureError(e);}finally{S.switching=false;update();}
138
+ }
139
+ async function loadHistory(){
140
+ $('history').replaceChildren();
141
+ for(const row of examples.filter(r=>r.model===S.model.id)){
142
+ const b=document.createElement('button');b.className='history-row';b.textContent=row.tokens+' tokens · Sky explanation';b.title=row.prompt;
143
+ b.onclick=()=>openExample(row.model).catch(captureError);$('history').append(b);
144
+ }
145
+ }
146
+ function loadTrace(d){
147
+ const model=validateObservatoryTrace(d,S.models);if(S.model.id!==model.id)applyModel(model,false);S.stream?.close();reset();S.trace=d;S.id=d.id;S.start=d.start;S.frames=d.frames;S.frame=Math.max(-1,S.frames.length-1);S.live=false;S.output=S.frames.map(f=>f.token_bytes?S.decoder.decode(new Uint8Array(f.token_bytes),{stream:true}):f.text).join('')+S.decoder.decode();$('prompt').value=d.prompt||'';
148
+ $('runNote').textContent='Recorded capture. Replay or select a token to inspect it.';renderCapture(d);$('timing').textContent=`${S.frames.length} tokens · recorded trace`;renderTerminal();update();loadHistory();toast(S.model.short_name+' measured trace loaded.');
149
+ }
150
+ function download(){if(!S.trace)return;const a=document.createElement('a');a.download=S.model.id+'-trace.json';a.href=URL.createObjectURL(new Blob([JSON.stringify(S.trace)],{type:'application/json'}));a.click();setTimeout(()=>URL.revokeObjectURL(a.href),1000);}
151
+ function mapPoint(ev){
152
+ const b=$('modelCanvas').getBoundingClientRect(),x=ev.clientX-b.left,y=ev.clientY-b.top,g=S.geometry;if(!g)return null;const layer=Math.floor((y-g.top)/g.rh);if(layer<0||layer>=layerCount())return null;
153
+ if(g.history){const frame=Math.floor((x-g.left)/g.cw);return frame>=0&&frame<S.frames.length?{layer,frame,x,y}:null;}
154
+ const head=x>=g.hx&&x<g.hx+g.headW?Math.floor((x-g.hx)/g.headW*headCount(layer)):null,expert=x>=g.ex&&x<g.ex+g.expW&&isMoe(layer)?Math.floor((x-g.ex)/g.expW*64)+64*Math.max(0,Math.min(3,Math.floor(((y-g.top-layer*g.rh)/g.rh-.1)/.8*4))):null;
155
+ return {layer,head,expert,ffn:!isMoe(layer)&&x>=g.ex&&x<g.ex+g.expW,x,y};
156
+ }
157
+ function initControls(){
158
+ $('shareButton').onclick=async()=>{const url=new URL(location.href);url.searchParams.set('layer',S.layer);url.searchParams.set('token',S.frame+1);try{await navigator.clipboard.writeText(url.href);toast('Example view link copied. Imported traces are not included.');}catch{toast('Copy the address from your browser to share this model.');}};
159
+ $('modelSelect').onchange=()=>switchModel($('modelSelect').value);$('openBlock').onclick=()=>openDetail('block');$('flowAttention').onclick=()=>openDetail('head');$('flowMlp').onclick=()=>openDetail(isMoe()?'expert':'ffn');$('sharedExpert').onclick=()=>openDetail('shared');
160
+ $('runButton').onclick=()=>{if(S.frames.length){selectFrame(0);startPlayback(false);}else openExample(S.model.id).catch(captureError);};
161
+ $('prevLayer').onclick=()=>selectLayer(S.layer-1);$('nextLayer').onclick=()=>selectLayer(S.layer+1);$('scrubber').oninput=()=>selectFrame(Number($('scrubber').value));$('stepBack').onclick=()=>selectFrame(S.frame-1);$('stepForward').onclick=()=>selectFrame(S.frame+1);$('liveButton').onclick=()=>selectFrame(S.frames.length-1);$('playButton').onclick=togglePlayback;$('playSpeed').onchange=()=>changeSpeed($('playSpeed').value);
162
+ $('structureButton').onclick=()=>{S.view='structure';$('structureButton').classList.add('selected');$('historyButton').classList.remove('selected');requestDraw();};$('historyButton').onclick=()=>{S.view='history';$('historyButton').classList.add('selected');$('structureButton').classList.remove('selected');requestDraw();};
163
+ $('modelCanvas').onkeydown=e=>{if(e.key==='ArrowDown'||e.key==='ArrowUp'){e.preventDefault();selectLayer(S.layer+(e.key==='ArrowDown'?1:-1));}if(e.key==='Enter'){e.preventDefault();openDetail('block');}};$('modelCanvas').onclick=e=>{const p=mapPoint(e);if(!p)return;S.layer=p.layer;S.head=Math.min(S.head,headCount()-1);if(p.frame!==undefined){selectFrame(p.frame);openDetail('block');}else if(p.head!==null&&p.head!==undefined)openDetail('head',p.head);else if(p.expert!==null&&p.expert!==undefined)openDetail('expert',p.expert);else if(p.ffn)openDetail('ffn');else if(isMoe()&&Math.abs(p.x-S.geometry.sx)<9)openDetail('shared');else openDetail('block');};
164
+ $('modelCanvas').onmousemove=e=>{const p=mapPoint(e),tip=$('mapTooltip');if(!p){tip.hidden=true;return;}const d=(p.frame!==undefined?S.frames[p.frame].layers:current())[p.layer];let text=`Layer ${pad(p.layer)} · ${attentionLabel(p.layer)}`;if(p.head!==null&&p.head!==undefined)text+=`\n${isLinear(p.layer)?'Value head':'Head'} ${pad(p.head)}${d?.heads?' · '+fmt(d.heads[p.head])+' output RMS':''}`;if(p.expert!==null&&p.expert!==undefined){const i=d?.experts?.indexOf(p.expert)??-1;text+=`\nExpert ${p.expert}${d?i>=0?' · selected · '+pct(d.weights[i]):' · not selected':' · awaiting trace'}`;}if(p.ffn)text+='\nDense FFN · '+S.config.intermediate_size+(Number.isFinite(d?.ffn)?' · '+fmt(d.ffn)+' RMS':'');tip.textContent=text;tip.hidden=false;tip.style.left=Math.max(0,Math.min(p.x+12,S.geometry.w-230))+'px';tip.style.top=Math.min(p.y+12,S.geometry.h-70)+'px';};$('modelCanvas').onmouseleave=()=>$('mapTooltip').hidden=true;
165
+ $('exportButton').onclick=download;$('importButton').onclick=()=>$('importFile').click();$('importFile').onchange=async e=>{let loading=false;try{if(S.running||S.requesting||S.loadingTrace)throw new Error('Stop the current generation before importing a trace.');const f=e.target.files[0];if(!f)return;if(f.size>160000000)throw new Error('Trace file exceeds 160 MB.');loading=true;S.loadingTrace=true;$('runButton').disabled=true;update();loadTrace(JSON.parse(await f.text()));}catch(e){toast(e.message);}finally{if(loading){S.loadingTrace=false;update();if(S.trace)renderCapture(S.trace);else $('runButton').disabled=false;}$('importFile').value='';}};
166
+ $('copyButton').onclick=async()=>{try{await navigator.clipboard.writeText(S.output);toast('Output copied.');}catch{toast('Select the output text to copy it.');}};$('aboutButton').onclick=()=>$('aboutDialog').showModal();$('metricInfo').onclick=()=>$('aboutDialog').showModal();$('closeAbout').onclick=()=>$('aboutDialog').close();
167
+ new ResizeObserver(requestDraw).observe($('mapContainer'));
168
+ }
169
+ async function init(){
170
+ try{
171
+ [S.models,examples]=await Promise.all([readJSON('models.json'),readJSON('traces/index.json')]);
172
+ $('modelSelect').replaceChildren();for(const m of S.models)$('modelSelect').add(new Option(m.title,m.id));
173
+ const query=new URL(location.href).searchParams,model=S.models.find(m=>m.id===query.get('model'))||S.models[0];
174
+ initControls();applyModel(model);await loadHistory();await openExample(model.id);
175
+ const layer=Number(query.get('layer')),frame=Number(query.get('token'));
176
+ if(query.has('layer')&&Number.isInteger(layer))selectLayer(layer);
177
+ if(query.has('token')&&Number.isInteger(frame))selectFrame(frame-1);
178
+
179
+ }catch(e){captureError(e);}
180
+ }
181
+
182
+ let examples=[];
183
+ const traceCache=new Map();
184
+ async function readJSON(file){const r=await fetch(file);if(!r.ok)throw new Error('Could not load '+file+'. Try reloading.');return r.json();}
185
+ async function sha256(bytes){return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256',bytes)),b=>b.toString(16).padStart(2,'0')).join('');}
186
+ function captureError(e){$('engineStatus').textContent='Trace unavailable';$('runNote').textContent=e.message;$('runButton').disabled=false;$('runButton').textContent='Retry trace';toast(e.message);}
187
+ function renderCapture(d){
188
+ if(!d)return;const settings=d.settings||{};
189
+ $('captureSettings').textContent='Temperature '+(settings.temperature??'unmeasured')+' · seed '+(settings.seed??'unmeasured')+' · reasoning '+(settings.reasoning?'on':'off');
190
+ $('engineStatus').replaceChildren(document.createElement('i'),document.createTextNode('Measured Q8 replay'));$('engineStatus').classList.add('ready');
191
+ $('runButton').textContent='▶ Replay from start';$('runButton').disabled=false;
192
+ $('traceOrigin').textContent=examples.some(e=>e.id===d.id)?'Example capture · '+S.frames.length+' tokens':'Imported capture · '+S.frames.length+' tokens';
193
+ }
194
+ async function openExample(id){
195
+ if(S.loadingTrace)return;const row=examples.find(r=>r.model===id);if(!row)throw new Error('No example capture is available for this model.');
196
+ S.loadingTrace=true;$('runButton').disabled=true;$('runNote').textContent='Loading measured capture…';update();
197
+ try{
198
+ let d=traceCache.get(id);
199
+ if(!d){
200
+ const response=await fetch(row.file);if(!response.ok)throw new Error('The example capture could not load. Try again.');
201
+ const compressed=await response.arrayBuffer();if(await sha256(compressed)!==row.gzip_sha256)throw new Error('Capture checksum failed. Reload to get the latest files.');
202
+ if(typeof DecompressionStream==='undefined')throw new Error('This browser needs gzip stream support. Open in a current Chrome, Firefox or Safari.');
203
+ const plain=await new Response(new Blob([compressed]).stream().pipeThrough(new DecompressionStream('gzip'))).arrayBuffer();
204
+ if(await sha256(plain)!==row.sha256)throw new Error('Decoded capture checksum failed. Reload to try again.');
205
+ d=JSON.parse(new TextDecoder().decode(plain));validateObservatoryTrace(d,S.models);traceCache.set(id,d);
206
+ }
207
+ loadTrace(d);selectFrame(0);$('runNote').textContent='Real tensor capture. Press Replay or select a token.';
208
+ }finally{S.loadingTrace=false;update();}
209
+ }
210
+
211
+ init();
config.json ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "FlintForCausalLM"
4
+ ],
5
+ "model_type": "flint",
6
+ "attention_bias": false,
7
+ "attention_dropout": 0.0,
8
+ "bos_token_id": 150000,
9
+ "decoder_sparse_step": 1,
10
+ "eos_token_id": [
11
+ 150001,
12
+ 150003,
13
+ 150005,
14
+ 150018
15
+ ],
16
+ "head_dim": 128,
17
+ "hidden_act": "silu",
18
+ "hidden_size": 2048,
19
+ "initializer_range": 0.02,
20
+ "intermediate_size": 6144,
21
+ "layer_types": [
22
+ "full_attention",
23
+ "full_attention",
24
+ "sliding_attention",
25
+ "sliding_attention",
26
+ "sliding_attention",
27
+ "full_attention",
28
+ "sliding_attention",
29
+ "sliding_attention",
30
+ "sliding_attention",
31
+ "full_attention",
32
+ "sliding_attention",
33
+ "sliding_attention",
34
+ "sliding_attention",
35
+ "full_attention",
36
+ "sliding_attention",
37
+ "sliding_attention",
38
+ "sliding_attention",
39
+ "full_attention",
40
+ "sliding_attention",
41
+ "sliding_attention",
42
+ "sliding_attention",
43
+ "full_attention",
44
+ "sliding_attention",
45
+ "sliding_attention",
46
+ "sliding_attention",
47
+ "full_attention",
48
+ "sliding_attention",
49
+ "sliding_attention",
50
+ "sliding_attention",
51
+ "full_attention",
52
+ "sliding_attention",
53
+ "sliding_attention",
54
+ "sliding_attention",
55
+ "full_attention",
56
+ "sliding_attention",
57
+ "sliding_attention",
58
+ "sliding_attention",
59
+ "full_attention",
60
+ "sliding_attention",
61
+ "sliding_attention",
62
+ "sliding_attention",
63
+ "full_attention",
64
+ "sliding_attention",
65
+ "sliding_attention",
66
+ "sliding_attention",
67
+ "full_attention",
68
+ "sliding_attention",
69
+ "sliding_attention",
70
+ "full_attention"
71
+ ],
72
+ "max_position_embeddings": 262144,
73
+ "mlp_only_layers": [
74
+ 0,
75
+ 1
76
+ ],
77
+ "moe_intermediate_size": 512,
78
+ "norm_topk_prob": true,
79
+ "num_attention_heads": 32,
80
+ "num_experts": 256,
81
+ "num_experts_per_tok": 6,
82
+ "num_hidden_layers": 49,
83
+ "num_key_value_heads": 4,
84
+ "no_rope_layer_indices": [
85
+ 0,
86
+ 1,
87
+ 5,
88
+ 9,
89
+ 13,
90
+ 17,
91
+ 21,
92
+ 25,
93
+ 29,
94
+ 33,
95
+ 37,
96
+ 41,
97
+ 45,
98
+ 48
99
+ ],
100
+ "output_router_logits": false,
101
+ "pad_token_id": 150001,
102
+ "rms_norm_eps": 1e-06,
103
+ "rope_theta": 10000.0,
104
+ "router_aux_loss_coef": 0.0005,
105
+ "router_score_function": "sigmoid",
106
+ "shared_expert_intermediate_size": 1024,
107
+ "sliding_window": 513,
108
+ "softmax_type": "learnable",
109
+ "tie_word_embeddings": false,
110
+ "torch_dtype": "bfloat16",
111
+ "use_cache": true,
112
+ "use_sliding_window": true,
113
+ "vocab_size": 150144,
114
+ "transformers_version": "5.12.1"
115
+ }
cover.png ADDED

Git LFS Details

  • SHA256: 7a2cbb4155ce8fdfdcce06557c84a02859c065db63fee94fe6743bba8beb333e
  • Pointer size: 131 Bytes
  • Size of remote file: 312 kB
detail.js ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+ let detailLayout='';
3
+ const detailNode=(tag,cls,text)=>{const n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=text;return n;};
4
+ function openDetail(kind,index){
5
+ if(!S.config)return;if(kind==='head'&&Number.isInteger(index))S.head=Math.min(headCount()-1,index);
6
+ if(kind==='expert')S.expert=Number.isInteger(index)?index:(S.expert??current()[S.layer]?.experts?.[0]??0);
7
+ if((kind==='expert'||kind==='shared')&&!isMoe())kind='ffn';if(kind==='ffn'&&isMoe())kind='block';S.detail=kind;
8
+ if(!$('detailDialog').open){$('detailDialog').showModal();document.body.classList.add('detail-open');}update();
9
+ }
10
+ function closeDetail(){$('detailDialog').close();}
11
+ function detailTokens(){return [...(S.start?.tokens||[]),...S.frames.map(f=>f.text)];}
12
+ function metric(id,value){$(id).textContent=value;}
13
+ function stat(id,label){return `<div><strong id="${id}"></strong><span>${label}</span></div>`;}
14
+ function circuitNode(title,subtitle,cls=''){return `<div class="circuit-node ${cls}"><strong>${title}</strong><span>${subtitle}</span></div>`;}
15
+ function circuitLink(label=''){return `<div class="circuit-link"><span>${label}</span><b>→</b></div>`;}
16
+ function denseCircuit(){return '<div class="component-circuit">'+circuitNode(S.config.hidden_size,'Input')+circuitLink()+circuitNode(S.config.intermediate_size,'Gated feed-forward')+circuitLink()+circuitNode(S.config.hidden_size,'Output')+'</div>';}
17
+ function makeHeadButtons(dest){for(let i=0;i<headCount();i++){const b=detailNode('button','detail-head');b.dataset.head=i;b.ariaLabel='Open '+(isLinear()?'linear value':'attention')+' head '+i;b.append(detailNode('span','head-meter'),detailNode('b','',pad(i)),detailNode('small','',''));b.onclick=()=>openDetail('head',i);dest.append(b);}}
18
+ function makeExpertButtons(dest){for(let i=0;i<S.config.num_experts;i++){const b=detailNode('button','detail-expert',String(i).padStart(3,'0'));b.dataset.expert=i;b.ariaLabel='Open expert '+i;b.onclick=()=>openDetail('expert',i);dest.append(b);}}
19
+ function buildDetail(){
20
+ const kind=S.detail,dense=!isMoe(),linear=isLinear(),hidden=S.config.hidden_size,body=$('detailBody');S.detailMetric='heads';
21
+ if(kind==='block'){
22
+ body.innerHTML=`<div class="detail-stats">${stat('dAttentionMode','Attention')}${stat('dHeadCount',linear?'Value / key heads':'Query / KV heads')}${stat('dRoutingCount',dense?'Feed-forward width':'Routed experts')}${stat('dResidual','Block output RMS')}</div>
23
+ <div class="block-diagram"><div class="flow-pillar">Hidden state <b>${hidden}</b></div><div class="flow-connector">↓ <span>RMSNorm</span></div>
24
+ <section class="detail-card"><div class="detail-card-heading"><h3>${linear?'Recurrent linear attention':'Attention'}</h3><span id="dAttentionCaption"></span></div><div id="dBlockHeads" class="detail-head-grid"></div><div class="card-caption">Each head produces ${headDimension()} values. Click a head to inspect ${linear?'its recurrent memory':'its attention'}.</div></section>
25
+ <div class="flow-connector">↓ <span>Output projection + residual → RMSNorm</span></div>
26
+ <section class="detail-card"><div class="detail-card-heading"><h3>${dense?'Dense feed-forward':'Mixture of experts'}</h3><span>${dense?'All units participate':S.config.num_experts_per_tok+' routed + 1 shared'}</span></div>
27
+ ${dense?denseCircuit()+'<button id="dBlockFfn" class="shared-detail-link">Inspect feed-forward ↗</button>':'<div id="dBlockRoutes" class="route-cards"></div><div class="expert-map-heading"><span>'+S.config.num_experts+' experts</span><button id="dBlockShared" class="shared-detail-link">Shared expert ↗</button></div><div id="dBlockExperts" class="detail-expert-grid"></div>'}</section>
28
+ <div class="flow-connector">↓ <span>+ residual</span></div><div class="flow-pillar">Block output <b id="dBlockOutput"></b></div></div>`;
29
+ makeHeadButtons($('dBlockHeads'));if(dense)$('dBlockFfn').onclick=()=>openDetail('ffn');else{makeExpertButtons($('dBlockExperts'));$('dBlockShared').onclick=()=>openDetail('shared');}
30
+ }else if(kind==='ffn'){
31
+ body.innerHTML=`<div class="detail-stats">${stat('dFfnInput','Hidden width')}${stat('dFfnWidth','Intermediate width')}${stat('dFfnRms','Feed-forward output RMS')}${stat('dFfnResidual','Block output RMS')}</div><section class="detail-card"><div class="detail-card-heading"><h3>Dense feed-forward</h3><span>SiLU gated network</span></div>${denseCircuit()}<div class="card-caption">Gate and value projections expand the hidden state. SiLU gating combines them, and the output projection returns to the hidden width. The dense branch runs for every token.</div></section><section class="detail-card timeline-card"><div class="detail-card-heading"><h3>Feed-forward output over tokens</h3><span>RMS</span></div><div id="dTimeline" class="detail-timeline"></div></section>`;
32
+ }else if(kind==='head'){
33
+ body.innerHTML=`<div class="component-selector"><label for="dHeadSelect">${linear?'Value head':'Query head'}</label><select id="dHeadSelect"></select><span id="dKvGroup"></span></div>
34
+ <div class="detail-stats">${stat('dHeadRms','Head output RMS')}${stat('dHeadDimension','Head dimension')}${stat('dKvHead',linear?'Shared key head':'Shared KV head')}${linear?stat('dStateRms','Recurrent state RMS'):stat('dEntropy','Token entropy, nats')}</div>
35
+ <div class="component-circuit head-circuit">${linear?circuitNode('Previous state',S.config.linear_key_head_dim+' × '+S.config.linear_value_head_dim)+circuitLink('× retention')+circuitNode('Delta update','Write gate β')+circuitLink('Query read')+circuitNode('Gated output',headDimension()+' values'):circuitNode('Query','','query-node')+circuitLink('Q × K')+circuitNode('Attention',S.model.learned_sink?'Softmax + learned sink':'Softmax + output gate')+circuitLink('Weighted V')+circuitNode('Head output',headDimension()+' values')}</div>
36
+ <div class="detail-columns"><section class="detail-card"><div class="detail-card-heading"><h3>${linear?'Recurrent memory':'Attention positions'}</h3><span>${linear?'Gated DeltaNet':'8 strongest'}</span></div>${linear?'<div id="dMemory" class="detail-recurrent"></div><p class="recurrent-explanation">Retention scales the previous memory. The write gate controls its delta update. The query reads the updated state, then normalization and gating shape the output.</p>':'<div id="dAttentionRows" class="detail-attention-rows"></div><div id="dAttentionMass" class="attention-mass"></div>'}</section>
37
+ <section class="detail-card"><div class="detail-card-heading"><h3>${linear?'All value heads':'All query heads'}</h3><span>${headCount()} ${linear?'V':'Q'} / ${keyHeadCount()} ${linear?'K':'KV'}</span></div><div id="dAllHeads" class="detail-head-grid compact"></div><div class="card-caption">Colour and bar height show measured output RMS. All heads execute.</div></section></div>
38
+ <section class="detail-card timeline-card"><div class="detail-card-heading"><h3>Head activity over tokens</h3>${linear?'<select id="dTimelineMetric" class="timeline-metric-select" aria-label="Head timeline measurement"><option value="heads">Output RMS</option><option value="state_rms">State RMS</option><option value="write_gate">Write gate</option><option value="retention">Retention</option></select>':'<span>Output RMS</span>'}</div><div id="dTimeline" class="detail-timeline"></div></section>`;
39
+ for(let i=0;i<headCount();i++)$('dHeadSelect').add(new Option('Head '+pad(i),i));$('dHeadSelect').onchange=()=>openDetail('head',Number($('dHeadSelect').value));makeHeadButtons($('dAllHeads'));if(linear)$('dTimelineMetric').onchange=()=>{S.detailMetric=$('dTimelineMetric').value;paintTimeline('head');};
40
+ }else{
41
+ body.innerHTML=`<div class="component-selector"><label for="dExpertSelect">Expert</label><select id="dExpertSelect"></select><span id="dExpertArchitecture"></span></div>
42
+ <div class="detail-stats">${stat('dExpertStatus','Current token')}${stat('dExpertWeight',kind==='shared'?'Output RMS':'Routing weight')}${stat('dExpertRank',kind==='shared'?'Participation':'Router rank')}${stat('dExpertFrequency','Selected tokens')}</div>
43
+ <div class="component-circuit expert-circuit">${circuitNode(hidden,'Input')}${circuitLink()}${circuitNode(kind==='shared'?S.config.shared_expert_intermediate_size:S.config.moe_intermediate_size,'Gated feed-forward','expert-core')}${circuitLink()}${circuitNode(hidden,'Expert output')}${circuitLink(kind==='shared'?'Shared branch':'× routing weight')}${circuitNode('Combine','Routed + shared')}</div>
44
+ <div class="detail-columns"><section class="detail-card"><div class="detail-card-heading"><h3>Current routing</h3><span>${S.config.num_experts_per_tok} of ${S.config.num_experts}</span></div><div id="dExpertRoutes" class="route-cards vertical"></div><div class="mixture-readings"><span>Routed mix <b id="dRoutedRms"></b></span><button id="dSharedLink">Shared expert <b id="dSharedRms"></b> ↗</button></div></section>
45
+ <section class="detail-card"><div class="detail-card-heading"><h3>Expert map</h3><span>Layer <b id="dExpertLayer"></b></span></div><div id="dAllExperts" class="detail-expert-grid"></div></section></div>
46
+ <section class="detail-card timeline-card"><div class="detail-card-heading"><h3 id="dExpertTimelineTitle"></h3><span id="dExpertTimelineMetric"></span></div><div id="dTimeline" class="detail-timeline"></div></section>`;
47
+ for(let i=0;i<S.config.num_experts;i++)$('dExpertSelect').add(new Option('Expert '+String(i).padStart(3,'0'),i));$('dExpertSelect').add(new Option('Shared expert','shared'));
48
+ $('dExpertSelect').onchange=()=>openDetail($('dExpertSelect').value==='shared'?'shared':'expert',Number($('dExpertSelect').value));makeExpertButtons($('dAllExperts'));$('dSharedLink').onclick=()=>openDetail('shared');
49
+ }body.scrollTop=0;
50
+ }
51
+ function paintHeads(dest,data){
52
+ const max=scaleFor(current());for(const b of dest.children){const h=Number(b.dataset.head),v=data?.heads?.[h];b.classList.toggle('selected',S.detail==='head'&&h===S.head);b.style.background=Number.isFinite(v)?colour(v,max):'';b.style.color=Number.isFinite(v)&&v/max>.6?'#f4f9eb':'';b.style.setProperty('--level',Number.isFinite(v)?Math.min(100,v/max*100)+'%':'0%');b.querySelector('small').textContent=Number.isFinite(v)?fmt(v):'·';b.title=`Head ${pad(h)} · ${isLinear()?'K':'KV'} ${keyHead(h)} · ${Number.isFinite(v)?fmt(v)+' output RMS':'awaiting trace'}`;b.ariaPressed=String(S.detail==='head'&&h===S.head);}
53
+ }
54
+ function paintExperts(dest,data){
55
+ for(const b of dest.children){const id=Number(b.dataset.expert),rank=data?.experts?.indexOf(id)??-1;b.classList.toggle('routed',rank>=0);b.classList.toggle('selected',S.detail==='expert'&&id===S.expert);b.style.background=rank>=0?colour(data.weights[rank],.27):'';b.style.color=rank>=0&&data.weights[rank]/.27>.6?'#f4f9eb':'';b.title=`Expert ${id} · ${rank>=0?'selected · '+pct(data.weights[rank]):data?'not selected':'awaiting routing'}`;b.ariaPressed=String(S.detail==='expert'&&id===S.expert);}
56
+ }
57
+ function paintRoutes(dest,data){
58
+ const signature=JSON.stringify([data?.experts,data?.weights,S.expert,S.detail]);if(dest.dataset.signature===signature)return;dest.dataset.signature=signature;dest.replaceChildren();if(!data?.experts){dest.append(detailNode('span','detail-empty','Run a prompt or open a saved trace to inspect routing.'));return;}
59
+ data.experts.forEach((id,i)=>{const b=detailNode('button','route-card');b.dataset.expert=id;b.classList.toggle('selected',S.detail==='expert'&&id===S.expert);b.style.setProperty('--weight',pct(data.weights[i]));b.append(detailNode('span','','Expert '+String(id).padStart(3,'0')),detailNode('strong','',pct(data.weights[i])),detailNode('i',''));b.onclick=()=>openDetail('expert',id);dest.append(b);});
60
+ }
61
+ function paintAttention(data){
62
+ const a=data?.attention?.[S.head],dest=$('dAttentionRows'),signature=JSON.stringify([a,S.head,S.frame,S.live,S.frames.length]);if(dest.dataset.signature===signature)return;dest.dataset.signature=signature;dest.replaceChildren();$('dAttentionMass').replaceChildren();
63
+ if(!a){dest.append(detailNode('span','detail-empty','Run a prompt or select a measured token to inspect attention.'));return;}
64
+ const tokens=detailTokens();for(const [pos,weight]of a.top){const row=detailNode('div','detail-attention-row');row.style.setProperty('--weight',pct(weight));const token=detailNode('code','',tokens[pos]?.replace(/\n/g,'↵')??'#'+pos);token.title=tokens[pos]??'';row.append(detailNode('span','attention-position','#'+pos),token,detailNode('strong','',pct(weight)));dest.append(row);}
65
+ const top=a.top.reduce((v,item)=>v+item[1],0);if(S.model.learned_sink)$('dAttentionMass').append(detailNode('span','','Learned sink '+pct(a.sink)));$('dAttentionMass').append(detailNode('span','','Other token positions '+pct(Math.max(0,1-(S.model.learned_sink?a.sink:0)-top))));
66
+ }
67
+ function paintMemory(data){
68
+ const dest=$('dMemory');if(!dest.children.length)for(const [key,label]of [['write_gate','Write gate'],['retention','Retention'],['state_rms','State RMS']]){const card=detailNode('div','memory-metric');card.dataset.metric=key;card.append(detailNode('strong',''),detailNode('span','',label));if(key!=='state_rms'){const meter=detailNode('div','memory-meter');meter.append(detailNode('i',''));card.append(meter);}dest.append(card);}
69
+ for(const card of dest.children){const v=data?.[card.dataset.metric]?.[S.head];card.querySelector('strong').textContent=Number.isFinite(v)?card.dataset.metric==='state_rms'?fmt(v):pct(v):'unmeasured';card.style.setProperty('--value',Number.isFinite(v)?pct(v):'0%');}
70
+ }
71
+ function paintTimeline(kind){
72
+ const dest=$('dTimeline'),field=isLinear()&&kind==='head'?S.detailMetric||'heads':'heads',percentage=kind==='expert'||['write_gate','retention'].includes(field),values=S.frames.map(f=>{const l=f.layers[S.layer];if(kind==='head')return l[field]?.[S.head];if(kind==='ffn')return l.ffn;if(kind==='shared')return l.shared;const i=l.experts?.indexOf(S.expert)??-1;return i>=0?l.weights[i]:0;}),max=Math.max(...values.filter(Number.isFinite),.00001);
73
+ dest.querySelector('.detail-empty')?.remove();while(dest.children.length>values.length)dest.lastChild.remove();
74
+ for(let i=0;i<values.length;i++){let b=dest.children[i];if(!b){b=detailNode('button','timeline-token');b.append(detailNode('span','timeline-bar'),detailNode('code',''),detailNode('small',''));b.onclick=()=>selectFrame(i);dest.append(b);}const v=values[i],label=S.frames[i].text.replace(/\n/g,'↵')||'∅';b.classList.toggle('selected',i===S.frame);b.classList.toggle('inactive',v===0);b.style.setProperty('--level',Number.isFinite(v)?Math.max(v>0?3:0,v/max*100)+'%':'0%');b.querySelector('code').textContent=label;b.querySelector('small').textContent=String(i+1);b.title=`Token ${i+1}: ${label} · ${Number.isFinite(v)?percentage?pct(v):fmt(v)+' RMS':'unmeasured'}`;b.ariaLabel=b.title;b.ariaPressed=String(i===S.frame);}
75
+ if(!values.length)dest.append(detailNode('span','detail-empty','A measured timeline appears after opening a capture.'));
76
+ }
77
+ function renderDetail(){
78
+ if(!$('detailDialog').open||!S.detail||!S.config)return;
79
+ const kind=S.detail,data=current()[S.layer],dense=!isMoe(),linear=isLinear(),key=S.model.id+':'+kind+':'+S.layer;if(key!==detailLayout){detailLayout=key;buildDetail();}
80
+ $('detailTitle').textContent=`Block ${pad(S.layer)}${kind==='head'?' / '+(linear?'Linear head ':'Attention head ')+pad(S.head):kind==='expert'?' / Expert '+String(S.expert).padStart(3,'0'):kind==='shared'?' / Shared expert':kind==='ffn'?' / Feed-forward':''}`;
81
+ $('detailSubtitle').textContent=S.model.short_name+' · '+attentionLabel()+' · '+(dense?'Dense feed-forward':'Mixture of experts')+' · hidden size '+S.config.hidden_size;
82
+ document.querySelectorAll('[data-detail]').forEach(b=>{const selected=b.dataset.detail===(kind==='shared'||kind==='ffn'?'expert':kind);b.classList.toggle('selected',selected);b.ariaPressed=String(selected);b.disabled=false;if(b.dataset.detail==='expert')b.textContent=dense?'Feed-forward':'Experts';if(b.dataset.detail==='head')b.textContent=linear?'Linear attention':'Attention';});
83
+ $('detailPrev').disabled=S.layer===0;$('detailNext').disabled=S.layer===layerCount()-1;$('detailMode').textContent=S.running&&S.live?'Live capture':S.timer?'Playing measured trace':'Paused inspection';
84
+ if(kind==='block'){
85
+ metric('dAttentionMode',linear?'Gated DeltaNet':S.config.layer_types[S.layer]==='full_attention'?'Full context':S.config.sliding_window+'-token window');metric('dHeadCount',headCount()+' / '+keyHeadCount());metric('dRoutingCount',dense?String(S.config.intermediate_size):S.config.num_experts_per_tok+' / '+S.config.num_experts);metric('dResidual',fmt(data?.residual));metric('dBlockOutput',Number.isFinite(data?.residual)?fmt(data.residual)+' RMS':String(S.config.hidden_size));metric('dAttentionCaption',linear?'Recurrent state':attentionLabel());paintHeads($('dBlockHeads'),data);
86
+ if(!dense){paintRoutes($('dBlockRoutes'),data);paintExperts($('dBlockExperts'),data);$('dBlockShared').textContent='Shared expert · '+fmt(data?.shared)+' RMS ↗';}
87
+ }else if(kind==='ffn'){
88
+ metric('dFfnInput',String(S.config.hidden_size));metric('dFfnWidth',String(S.config.intermediate_size));metric('dFfnRms',fmt(data?.ffn));metric('dFfnResidual',fmt(data?.residual));paintTimeline(kind);
89
+ }else if(kind==='head'){
90
+ $('dHeadSelect').value=String(S.head);const group=headCount()/keyHeadCount(),start=keyHead()*group;metric('dKvGroup',linear?`Value head ${pad(S.head)} reads key head ${keyHead()} (${headCount()} V / ${keyHeadCount()} K)`:`Heads ${pad(start)} to ${pad(start+group-1)} share K and V`);metric('dHeadRms',fmt(data?.heads?.[S.head]));metric('dHeadDimension',String(headDimension()));metric('dKvHead',String(keyHead()));
91
+ if(linear){metric('dStateRms',fmt(data?.state_rms?.[S.head]));paintMemory(data);}else{metric('dEntropy',fmt(data?.attention?.[S.head]?.entropy));$('detailBody').querySelector('.query-node span').textContent='Head '+pad(S.head)+' · KV '+keyHead();paintAttention(data);}paintHeads($('dAllHeads'),data);paintTimeline(kind);
92
+ }else{
93
+ const shared=kind==='shared',rank=data?.experts?.indexOf(S.expert)??-1,selected=shared?Boolean(data):rank>=0,count=S.frames.filter(f=>shared||f.layers[S.layer].experts?.includes(S.expert)).length;
94
+ $('dExpertSelect').value=shared?'shared':String(S.expert);metric('dExpertArchitecture',shared?'Always-active shared branch':'Layer-local routed expert');metric('dExpertStatus',data?(selected?'Selected':'Not selected'):'Awaiting trace');$('dExpertStatus').classList.toggle('is-active',selected);metric('dExpertWeight',shared?fmt(data?.shared):data?pct(rank>=0?data.weights[rank]:0):'unmeasured');metric('dExpertRank',shared?'Every token':rank>=0?String(rank+1)+' / '+S.config.num_experts_per_tok:data?'Outside top '+S.config.num_experts_per_tok:'unmeasured');metric('dExpertFrequency',count+' / '+S.frames.length);metric('dExpertLayer',pad(S.layer));metric('dRoutedRms',fmt(data?.routed)+' RMS');metric('dSharedRms',fmt(data?.shared)+' RMS');metric('dExpertTimelineTitle',shared?'Shared output over tokens':'Expert selection over tokens');metric('dExpertTimelineMetric',shared?'RMS':'Routing weight');$('detailBody').querySelector('.expert-core').classList.toggle('engaged',selected);paintRoutes($('dExpertRoutes'),data);paintExperts($('dAllExperts'),data);paintTimeline(kind);
95
+ }renderDetailPlayback();
96
+ }
97
+ function renderDetailPlayback(){
98
+ const n=S.frames.length,f=S.frames[S.frame],partial=S.live&&S.running&&S.partial.length;$('detailFrameLabel').textContent=`TOKEN ${Math.max(0,S.frame+1)} / ${n}`;$('detailToken').textContent=partial?'Capturing next token…':f?f.text.replace(/\n/g,'↵')||'∅':'Awaiting trace';$('detailToken').title=f?.text||'';$('detailInputPosition').textContent=partial?'Forward pass in progress':f?'Input position '+f.input_position:'';
99
+ $('detailPlay').disabled=!n;$('detailPlay').textContent=S.timer?'Ⅱ':'▶';$('detailPlay').ariaLabel=S.timer?'Pause trace':'Play trace';$('detailStepBack').disabled=S.frame<=0;$('detailStepForward').disabled=S.frame>=n-1;$('detailSpeed').value=String(S.speed);$('detailLive').classList.toggle('selected',S.live);$('detailScrubber').disabled=!n;$('detailScrubber').max=Math.max(0,n-1);$('detailScrubber').value=Math.max(0,S.frame);$('detailPlaybackNote').textContent=S.live&&S.running?'Choose a speed to slow the captured frames.':S.running?'Replay · inference continues':S.timer?'Measured trace playback':'Step, scrub or play the measured trace.';
100
+ }
101
+ function initDetail(){
102
+ $('detailSpeed').innerHTML=$('playSpeed').innerHTML;$('detailBack').onclick=closeDetail;$('detailClose').onclick=closeDetail;$('detailDialog').addEventListener('close',()=>{S.detail=null;detailLayout='';document.body.classList.remove('detail-open');});$('detailPrev').onclick=()=>selectLayer(S.layer-1);$('detailNext').onclick=()=>selectLayer(S.layer+1);
103
+ document.querySelectorAll('[data-detail]').forEach(b=>b.onclick=()=>openDetail(b.dataset.detail==='expert'&&!isMoe()?'ffn':b.dataset.detail));$('detailPlay').onclick=togglePlayback;$('detailStepBack').onclick=()=>selectFrame(S.frame-1);$('detailStepForward').onclick=()=>selectFrame(S.frame+1);$('detailScrubber').oninput=()=>selectFrame(Number($('detailScrubber').value));$('detailSpeed').onchange=()=>changeSpeed($('detailSpeed').value);$('detailLive').onclick=()=>selectFrame(S.frames.length-1);
104
+ $('detailDialog').addEventListener('keydown',e=>{if(/INPUT|SELECT|BUTTON/.test(e.target.tagName))return;if(e.code==='Space'){e.preventDefault();togglePlayback();}if(e.key==='ArrowLeft'){e.preventDefault();selectFrame(S.frame-1);}if(e.key==='ArrowRight'){e.preventDefault();selectFrame(S.frame+1);}});
105
+ }
106
+ initDetail();
favicon.svg ADDED
index.html CHANGED
@@ -1,19 +1,39 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Flint &amp; Qwen Model Observatory | alphaBell</title><meta name="description" content="Explore Flint expert routing and Qwen recurrent memory with real Q8 tensor captures. Replay every token, inspect every block and import your own trace."><meta property="og:title" content="Model Observatory by alphaBell"><meta property="og:description" content="Two architectures. Real tensor captures. Every token."><meta property="og:image" content="https://huggingface.co/spaces/alphabell/Model-Observatory/resolve/main/cover.png"><meta name="theme-color" content="#176b59"><link rel="icon" href="favicon.svg"><link rel="stylesheet" href="style.css"></head>
4
+ <body>
5
+ <header class="models-header"><div class="header-start"><a class="brand" href="./"><span class="brand-icon">α</span><span>alphaBell<span class="brand-divider">/</span><b>observatory</b></span></a><label class="model-control"><span>MODEL</span><select id="modelSelect" aria-label="Model" disabled><option>Recursive Flint</option></select></label></div><div class="header-end"><span class="engine-status" id="engineStatus"><i></i>Loading capture</span><button class="icon-button" id="aboutButton" title="How to read the model" aria-label="How to read the model">?</button></div></header>
6
+ <section class="overview"><div><div class="eyebrow" id="modelEyebrow">MODEL OBSERVATORY</div><h1>Inside Flint &amp; Qwen.</h1></div><div class="stats" id="modelStats"></div></section>
7
+ <main>
8
+ <aside class="input-panel">
9
+ <section class="prompt-section"><div class="section-heading"><h2>01 <span>Measured capture</span></h2><span class="small-tag" id="quantization">Q8_0</span></div><p id="traceOrigin" class="trace-origin">Opening example capture…</p><label class="sr-only" for="prompt" id="promptLabel">Captured prompt</label><textarea id="prompt" readonly spellcheck="false">Explain why the sky is blue in two sentences.</textarea><p class="capture-settings" id="captureSettings"></p><button id="runButton" class="primary" disabled>Loading capture…</button><p id="runNote" class="run-note" role="status">Structure is ready while the capture loads.</p><details class="capture-help"><summary>Use your own capture</summary><p>Import a compatible Flint or Qwen trace JSON. It stays in your browser. This public viewer replays measured captures; new prompts need a separate capture engine.</p><a href="https://huggingface.co/spaces/alphabell/Model-Observatory/blob/main/TRACE-FORMAT.md" target="_blank" rel="noreferrer">Trace format ↗</a></details></section>
10
+ <section class="terminal-section"><div class="section-heading terminal-heading"><h2>02 <span>Output</span></h2><span id="tokenCount">0 tokens</span></div><div id="terminal" tabindex="0" aria-label="Model output"><span class="terminal-welcome">model &gt; opening measured capture<span class="cursor">▌</span></span></div><div class="terminal-footer"><span id="timing">Recorded capture</span><button id="copyButton" title="Copy output" aria-label="Copy output">Copy</button></div></section>
11
+ <section class="saved-section"><div class="section-heading"><h2>Example traces</h2><button id="importButton" class="text-button">Import ↗</button><input id="importFile" type="file" accept="application/json,.json" hidden></div><div id="history" class="history"><span class="muted">Open a measured capture.</span></div></section>
12
+ </aside>
13
+ <section class="model-panel">
14
+ <div class="model-toolbar"><div class="section-heading"><h2>03 <span>Model structure</span></h2></div><div class="view-switch" role="group" aria-label="Model visualization"><button class="selected" id="structureButton">Structure</button><button id="historyButton">Token history</button></div></div>
15
+ <div class="map-legend"><span><i class="swatch full"></i>Full attention</span><span><i class="swatch sliding" id="legendSecondarySwatch"></i><span id="legendSecondary">Sliding window</span></span><span><i class="swatch active"></i><span id="legendActivation">Selected expert</span></span></div>
16
+ <div class="model-map" id="mapContainer"><canvas tabindex="0" id="modelCanvas" aria-label="Model architecture. Click a block, head or feed-forward branch to inspect it." role="button"></canvas><div class="map-tooltip" id="mapTooltip" hidden></div></div>
17
+ <div class="model-footer"><span><i class="status-dot"></i><span id="captureLabel">Waiting for measured activations</span></span><span>Brightness = output RMS <button class="tiny-info" id="metricInfo" aria-label="Explain brightness">?</button></span></div>
18
+ </section>
19
+ <aside class="inspector-panel">
20
+ <div class="section-heading"><h2>04 <span>Inspect a layer</span></h2><div class="layer-nav"><button id="prevLayer" aria-label="Previous layer">‹</button><button id="nextLayer" aria-label="Next layer">›</button></div></div>
21
+ <div class="layer-title"><button id="openBlock" class="open-block" title="Open block fullscreen">Layer <span id="layerNumber">12</span> ↗</button><span id="layerType" class="small-tag">Sliding</span></div>
22
+ <div class="layer-flow"><span>RMSNorm</span><span>↓</span><button id="flowAttention">Sliding-window attention</button><span>+ residual</span><span>↓</span><button id="flowMlp">Mixture of experts</button><span>+ residual</span></div>
23
+ <section class="inspector-section"><div class="inspector-heading"><h4 id="headGridTitle">Attention heads</h4><span id="headGridCount"></span></div><div class="head-grid" id="headGrid"></div><div class="scale"><span>Lower RMS</span><i></i><span>Higher RMS</span></div><div class="head-reading"><span id="headLabel">Head 00</span><strong id="headValue">Awaiting trace</strong></div></section>
24
+ <section class="inspector-section expert-section"><div class="inspector-heading"><h4 id="expertTitle">Expert routing</h4><span id="expertCount">6 of 256</span></div><div id="expertGrid" class="expert-grid"></div><div id="expertList" class="expert-list"><span class="muted">Open a measured capture to see selected experts.</span></div><button class="shared-expert" id="sharedExpert" title="Open shared expert fullscreen"><i></i><span>Shared expert ↗</span><strong id="sharedValue">Always active</strong></button></section>
25
+ <section class="inspector-section attention-section"><div class="inspector-heading"><h4 id="attentionTitle">Where this head attends</h4><span id="attentionCount">top 8 positions</span></div><div id="attentionList" class="attention-list"><span class="muted">Select a token to inspect its attention.</span></div></section>
26
+ </aside>
27
+ </main>
28
+ <section class="playback"><div class="playback-bar"><div class="playback-controls"><button id="playButton" title="Play or pause trace" aria-label="Play trace">▶</button><button id="stepBack" aria-label="Previous token">‹</button><button id="stepForward" aria-label="Next token">›</button><span id="frameLabel">TOKEN 000 / 000</span></div><div class="playback-options"><select id="playSpeed" aria-label="Playback speed"><option value="8000">1 token / 8 s</option><option value="4000">1 token / 4 s</option><option value="2000">1 token / 2 s</option><option value="1000">1 token / s</option><option value="500" selected>2 tokens / s</option><option value="250">4 tokens / s</option></select><button id="liveButton" ><i></i>Jump to end</button><button id="exportButton" disabled>Export trace ↓</button></div></div><label class="sr-only" for="scrubber">Select generated token</label><input id="scrubber" type="range" min="0" max="0" value="0" disabled><div id="tokenStrip" class="token-strip"><span class="muted">Select a token to inspect its measured frame.</span></div></section>
29
+ <dialog id="detailDialog" class="detail-dialog" aria-labelledby="detailTitle">
30
+ <div class="detail-header"><div><button id="detailBack" class="detail-back">↖ Model overview</button><h2 id="detailTitle">Block 12</h2><div id="detailSubtitle" class="detail-subtitle"></div></div><div class="detail-navigation"><button id="detailPrev" aria-label="Previous block">‹</button><button id="detailNext" aria-label="Next block">›</button><button id="detailClose" aria-label="Close fullscreen view">×</button></div></div>
31
+ <div class="detail-tabs" role="group" aria-label="Component view"><button data-detail="block">Block</button><button data-detail="head">Attention</button><button data-detail="expert">Experts</button><span id="detailMode"></span></div>
32
+ <div id="detailBody" class="detail-body"></div>
33
+ <div class="detail-playback"><div class="detail-token-context"><span id="detailFrameLabel"></span><code id="detailToken"></code><span id="detailInputPosition"></span></div><div class="detail-control-row"><div class="playback-controls"><button id="detailPlay" aria-label="Play trace">▶</button><button id="detailStepBack" aria-label="Previous token">‹</button><button id="detailStepForward" aria-label="Next token">›</button></div><label class="detail-speed">Speed <select id="detailSpeed" aria-label="Fullscreen playback speed"></select></label><button id="detailLive" class="detail-live">Jump to end</button><span id="detailPlaybackNote"></span></div><label class="sr-only" for="detailScrubber">Fullscreen selected token</label><input id="detailScrubber" type="range" min="0" max="0" value="0" disabled></div>
34
+ </dialog>
35
+ <dialog id="aboutDialog"><button id="closeAbout" class="dialog-close" aria-label="Close explanation">×</button><div class="eyebrow">READING THE OBSERVATORY</div><h2>One token. The whole network.</h2><div id="aboutContent"></div><a id="aboutSource" target="_blank" rel="noreferrer">Model configuration ↗</a></dialog>
36
+ <div class="toast" id="toast" role="status" hidden></div>
37
+ <footer class="site-footer"><a href="https://alphabell.com" target="_blank" rel="noreferrer">alphaBell</a><span>Measured activations, local replay.</span><a href="https://huggingface.co/spaces/alphabell/Model-Observatory/tree/main" target="_blank" rel="noreferrer">Source ↗</a><button id="shareButton" class="text-button">Share view ↗</button></footer><noscript>Enable JavaScript to explore the model architecture and recorded traces.</noscript>
38
+ <script src="trace-validation.js"></script><script src="app.js" defer></script><script src="detail.js" defer></script>
39
+ </body></html>
models.json ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "id": "flint",
4
+ "title": "Recursive Flint",
5
+ "short_name": "Flint",
6
+ "family": "MoE transformer",
7
+ "quantization": "Q8_0",
8
+ "source_url": "https://huggingface.co/RecursiveSI/flint/blob/main/config.json",
9
+ "learned_sink": true,
10
+ "stats": [
11
+ [
12
+ "49",
13
+ "",
14
+ "layers"
15
+ ],
16
+ [
17
+ "32",
18
+ "",
19
+ "query heads / layer"
20
+ ],
21
+ [
22
+ "6",
23
+ "256",
24
+ "routed experts / token"
25
+ ],
26
+ [
27
+ "2.5B",
28
+ "39.8B",
29
+ "active parameters"
30
+ ]
31
+ ],
32
+ "architecture": {
33
+ "architectures": [
34
+ "FlintForCausalLM"
35
+ ],
36
+ "model_type": "flint",
37
+ "attention_bias": false,
38
+ "attention_dropout": 0,
39
+ "bos_token_id": 150000,
40
+ "decoder_sparse_step": 1,
41
+ "eos_token_id": [
42
+ 150001,
43
+ 150003,
44
+ 150005,
45
+ 150018
46
+ ],
47
+ "head_dim": 128,
48
+ "hidden_act": "silu",
49
+ "hidden_size": 2048,
50
+ "initializer_range": 0.02,
51
+ "intermediate_size": 6144,
52
+ "layer_types": [
53
+ "full_attention",
54
+ "full_attention",
55
+ "sliding_attention",
56
+ "sliding_attention",
57
+ "sliding_attention",
58
+ "full_attention",
59
+ "sliding_attention",
60
+ "sliding_attention",
61
+ "sliding_attention",
62
+ "full_attention",
63
+ "sliding_attention",
64
+ "sliding_attention",
65
+ "sliding_attention",
66
+ "full_attention",
67
+ "sliding_attention",
68
+ "sliding_attention",
69
+ "sliding_attention",
70
+ "full_attention",
71
+ "sliding_attention",
72
+ "sliding_attention",
73
+ "sliding_attention",
74
+ "full_attention",
75
+ "sliding_attention",
76
+ "sliding_attention",
77
+ "sliding_attention",
78
+ "full_attention",
79
+ "sliding_attention",
80
+ "sliding_attention",
81
+ "sliding_attention",
82
+ "full_attention",
83
+ "sliding_attention",
84
+ "sliding_attention",
85
+ "sliding_attention",
86
+ "full_attention",
87
+ "sliding_attention",
88
+ "sliding_attention",
89
+ "sliding_attention",
90
+ "full_attention",
91
+ "sliding_attention",
92
+ "sliding_attention",
93
+ "sliding_attention",
94
+ "full_attention",
95
+ "sliding_attention",
96
+ "sliding_attention",
97
+ "sliding_attention",
98
+ "full_attention",
99
+ "sliding_attention",
100
+ "sliding_attention",
101
+ "full_attention"
102
+ ],
103
+ "max_position_embeddings": 262144,
104
+ "mlp_only_layers": [
105
+ 0,
106
+ 1
107
+ ],
108
+ "moe_intermediate_size": 512,
109
+ "norm_topk_prob": true,
110
+ "num_attention_heads": 32,
111
+ "num_experts": 256,
112
+ "num_experts_per_tok": 6,
113
+ "num_hidden_layers": 49,
114
+ "num_key_value_heads": 4,
115
+ "no_rope_layer_indices": [
116
+ 0,
117
+ 1,
118
+ 5,
119
+ 9,
120
+ 13,
121
+ 17,
122
+ 21,
123
+ 25,
124
+ 29,
125
+ 33,
126
+ 37,
127
+ 41,
128
+ 45,
129
+ 48
130
+ ],
131
+ "output_router_logits": false,
132
+ "pad_token_id": 150001,
133
+ "rms_norm_eps": 1e-06,
134
+ "rope_theta": 10000,
135
+ "router_aux_loss_coef": 0.0005,
136
+ "router_score_function": "sigmoid",
137
+ "shared_expert_intermediate_size": 1024,
138
+ "sliding_window": 513,
139
+ "softmax_type": "learnable",
140
+ "tie_word_embeddings": false,
141
+ "torch_dtype": "bfloat16",
142
+ "use_cache": true,
143
+ "use_sliding_window": true,
144
+ "vocab_size": 150144,
145
+ "transformers_version": "5.12.1"
146
+ }
147
+ },
148
+ {
149
+ "id": "qwen",
150
+ "title": "Qwen3.8-27B",
151
+ "short_name": "Qwen",
152
+ "family": "Hybrid recurrent transformer",
153
+ "quantization": "Q8_0",
154
+ "source_url": "https://huggingface.co/Qwen/Qwen3.8-27B/blob/main/config.json",
155
+ "learned_sink": false,
156
+ "stats": [
157
+ [
158
+ "64",
159
+ "",
160
+ "layers"
161
+ ],
162
+ [
163
+ "48",
164
+ "24",
165
+ "linear / full heads"
166
+ ],
167
+ [
168
+ "17408",
169
+ "",
170
+ "dense FFN width"
171
+ ],
172
+ [
173
+ "5120",
174
+ "",
175
+ "hidden width"
176
+ ]
177
+ ],
178
+ "architecture": {
179
+ "architectures": [
180
+ "Qwen3_5ForConditionalGeneration"
181
+ ],
182
+ "model_type": "qwen3_5_text",
183
+ "num_hidden_layers": 64,
184
+ "hidden_size": 5120,
185
+ "intermediate_size": 17408,
186
+ "num_attention_heads": 24,
187
+ "num_key_value_heads": 4,
188
+ "head_dim": 256,
189
+ "attn_output_gate": true,
190
+ "full_attention_interval": 4,
191
+ "layer_types": [
192
+ "linear_attention",
193
+ "linear_attention",
194
+ "linear_attention",
195
+ "full_attention",
196
+ "linear_attention",
197
+ "linear_attention",
198
+ "linear_attention",
199
+ "full_attention",
200
+ "linear_attention",
201
+ "linear_attention",
202
+ "linear_attention",
203
+ "full_attention",
204
+ "linear_attention",
205
+ "linear_attention",
206
+ "linear_attention",
207
+ "full_attention",
208
+ "linear_attention",
209
+ "linear_attention",
210
+ "linear_attention",
211
+ "full_attention",
212
+ "linear_attention",
213
+ "linear_attention",
214
+ "linear_attention",
215
+ "full_attention",
216
+ "linear_attention",
217
+ "linear_attention",
218
+ "linear_attention",
219
+ "full_attention",
220
+ "linear_attention",
221
+ "linear_attention",
222
+ "linear_attention",
223
+ "full_attention",
224
+ "linear_attention",
225
+ "linear_attention",
226
+ "linear_attention",
227
+ "full_attention",
228
+ "linear_attention",
229
+ "linear_attention",
230
+ "linear_attention",
231
+ "full_attention",
232
+ "linear_attention",
233
+ "linear_attention",
234
+ "linear_attention",
235
+ "full_attention",
236
+ "linear_attention",
237
+ "linear_attention",
238
+ "linear_attention",
239
+ "full_attention",
240
+ "linear_attention",
241
+ "linear_attention",
242
+ "linear_attention",
243
+ "full_attention",
244
+ "linear_attention",
245
+ "linear_attention",
246
+ "linear_attention",
247
+ "full_attention",
248
+ "linear_attention",
249
+ "linear_attention",
250
+ "linear_attention",
251
+ "full_attention",
252
+ "linear_attention",
253
+ "linear_attention",
254
+ "linear_attention",
255
+ "full_attention"
256
+ ],
257
+ "linear_conv_kernel_dim": 4,
258
+ "linear_key_head_dim": 128,
259
+ "linear_value_head_dim": 128,
260
+ "linear_num_key_heads": 16,
261
+ "linear_num_value_heads": 48,
262
+ "mamba_ssm_dtype": "float32",
263
+ "rms_norm_eps": 1e-06,
264
+ "max_position_embeddings": 262144,
265
+ "vocab_size": 248320,
266
+ "partial_rotary_factor": 0.25,
267
+ "rope_parameters": {
268
+ "mrope_interleaved": true,
269
+ "mrope_section": [
270
+ 11,
271
+ 11,
272
+ 10
273
+ ],
274
+ "partial_rotary_factor": 0.25,
275
+ "rope_theta": 10000000,
276
+ "rope_type": "default"
277
+ },
278
+ "tie_word_embeddings": false,
279
+ "hidden_act": "silu",
280
+ "num_experts": 0,
281
+ "first_k_dense_replace": 64
282
+ }
283
+ }
284
+ ]
models/qwen.json ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3_5ForConditionalGeneration"
4
+ ],
5
+ "model_type": "qwen3_5_text",
6
+ "num_hidden_layers": 64,
7
+ "hidden_size": 5120,
8
+ "intermediate_size": 17408,
9
+ "num_attention_heads": 24,
10
+ "num_key_value_heads": 4,
11
+ "head_dim": 256,
12
+ "attn_output_gate": true,
13
+ "full_attention_interval": 4,
14
+ "layer_types": [
15
+ "linear_attention",
16
+ "linear_attention",
17
+ "linear_attention",
18
+ "full_attention",
19
+ "linear_attention",
20
+ "linear_attention",
21
+ "linear_attention",
22
+ "full_attention",
23
+ "linear_attention",
24
+ "linear_attention",
25
+ "linear_attention",
26
+ "full_attention",
27
+ "linear_attention",
28
+ "linear_attention",
29
+ "linear_attention",
30
+ "full_attention",
31
+ "linear_attention",
32
+ "linear_attention",
33
+ "linear_attention",
34
+ "full_attention",
35
+ "linear_attention",
36
+ "linear_attention",
37
+ "linear_attention",
38
+ "full_attention",
39
+ "linear_attention",
40
+ "linear_attention",
41
+ "linear_attention",
42
+ "full_attention",
43
+ "linear_attention",
44
+ "linear_attention",
45
+ "linear_attention",
46
+ "full_attention",
47
+ "linear_attention",
48
+ "linear_attention",
49
+ "linear_attention",
50
+ "full_attention",
51
+ "linear_attention",
52
+ "linear_attention",
53
+ "linear_attention",
54
+ "full_attention",
55
+ "linear_attention",
56
+ "linear_attention",
57
+ "linear_attention",
58
+ "full_attention",
59
+ "linear_attention",
60
+ "linear_attention",
61
+ "linear_attention",
62
+ "full_attention",
63
+ "linear_attention",
64
+ "linear_attention",
65
+ "linear_attention",
66
+ "full_attention",
67
+ "linear_attention",
68
+ "linear_attention",
69
+ "linear_attention",
70
+ "full_attention",
71
+ "linear_attention",
72
+ "linear_attention",
73
+ "linear_attention",
74
+ "full_attention",
75
+ "linear_attention",
76
+ "linear_attention",
77
+ "linear_attention",
78
+ "full_attention"
79
+ ],
80
+ "linear_conv_kernel_dim": 4,
81
+ "linear_key_head_dim": 128,
82
+ "linear_value_head_dim": 128,
83
+ "linear_num_key_heads": 16,
84
+ "linear_num_value_heads": 48,
85
+ "mamba_ssm_dtype": "float32",
86
+ "rms_norm_eps": 0.000001,
87
+ "max_position_embeddings": 262144,
88
+ "vocab_size": 248320,
89
+ "partial_rotary_factor": 0.25,
90
+ "rope_parameters": {
91
+ "mrope_interleaved": true,
92
+ "mrope_section": [
93
+ 11,
94
+ 11,
95
+ 10
96
+ ],
97
+ "partial_rotary_factor": 0.25,
98
+ "rope_theta": 10000000,
99
+ "rope_type": "default"
100
+ },
101
+ "tie_word_embeddings": false,
102
+ "hidden_act": "silu",
103
+ "num_experts": 0,
104
+ "first_k_dense_replace": 64
105
+ }
package.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "alphabell-model-observatory",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "Real Flint and Qwen tensor captures, explored token by token",
6
+ "author": "alphaBell",
7
+ "license": "MIT",
8
+ "scripts": { "test": "node --test tests/*.test.cjs" }
9
+ }
preview.png ADDED

Git LFS Details

  • SHA256: 65351c80dec8fc1e7b7dc635486da9bb9a2de48017b099cc4a97358c1c4d143a
  • Pointer size: 131 Bytes
  • Size of remote file: 351 kB
requirements-dev.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ playwright==1.64.1
sources.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "configurations": {
3
+ "RecursiveSI/flint": {
4
+ "sha": "2a247be0c0aec895ccb0ac7ca92229ec6df37288",
5
+ "config": "https://huggingface.co/RecursiveSI/flint/resolve/2a247be0c0aec895ccb0ac7ca92229ec6df37288/config.json"
6
+ },
7
+ "Qwen/Qwen3.8-27B": {
8
+ "sha": "1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0",
9
+ "config": "https://huggingface.co/Qwen/Qwen3.8-27B/resolve/1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0/config.json"
10
+ }
11
+ },
12
+ "capture_engine": {
13
+ "project": "llama.cpp",
14
+ "commit": "74686f08"
15
+ },
16
+ "checks": {
17
+ "flint_matched_configuration_fields": 38,
18
+ "qwen_matched_configuration_fields": 23,
19
+ "differences": 0
20
+ }
21
+ }
style.css CHANGED
@@ -1,28 +1,142 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
- }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }
 
1
+ :root{--bg:#f6f7f3;--paper:#fff;--ink:#24372f;--muted:#89918c;--line:#e5e9e2;--green:#176b59;--lime:#d5f59b;--mono:ui-monospace,SFMono-Regular,Consolas,monospace;--sans:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:13px}button,input,textarea,select{font:inherit}button{cursor:pointer}button:disabled{cursor:default;opacity:.45}button{color:inherit}button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--green);outline-offset:3px}button[hidden],[hidden]{display:none!important}header{height:68px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;padding:0 30px;background:#fff}.brand{display:flex;gap:12px;align-items:center;color:var(--ink);text-decoration:none;font-size:23px;letter-spacing:-.8px}.brand b{font-weight:450;color:#758078;font-size:19px}.brand-icon{display:flex;align-items:center;justify-content:center;border-radius:9px;width:31px;height:34px;background:var(--green);color:var(--lime);font-weight:700;font-size:30px;font-style:italic}.brand-divider{margin:0 12px;color:#c7cec8;font-weight:400}.header-end{display:flex;align-items:center;gap:18px}.engine-status{display:flex;gap:8px;align-items:center;font-size:11px}.engine-status i,.status-dot{width:6px;height:6px;background:#a4ada7;border-radius:50%;display:inline-block}.engine-status.ready i{background:#56966b}.icon-button,.tiny-info{border:1px solid #d7ded6;border-radius:50%;background:none;width:23px;height:23px;font:12px var(--mono)}.overview{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:26px 30px 25px}.eyebrow{font:10px var(--mono);letter-spacing:1.5px;color:var(--green)}h1{font-size:26px;font-weight:500;letter-spacing:-1px;margin:7px 0 0}.stats{display:flex;gap:35px}.stats>div{display:flex;flex-direction:column;gap:6px}.stats strong{font-size:24px;font-weight:500;letter-spacing:-.7px}.stats small{font-size:15px;color:#8a938b;font-weight:400}.stats span{color:#869087;font-size:10px}main{margin:0 24px;display:grid;grid-template-columns:270px minmax(420px,1fr) 290px;border:1px solid var(--line);border-radius:12px;overflow:hidden;height:calc(100vh - 325px);min-height:660px;background:var(--paper)}.input-panel{display:flex;flex-direction:column;border-right:1px solid var(--line);min-width:0}.section-heading{display:flex;justify-content:space-between;align-items:center;gap:10px}h2{font-size:10px;letter-spacing:.5px;font-weight:500;margin:0;color:#9aa39a}h2 span{font-size:12px;color:var(--ink);letter-spacing:0;margin-left:7px}button.text-button{background:none;border:0;color:#77857a;padding:0;font-size:10px}.prompt-section{padding:19px 19px 17px}.small-tag{border:1px solid var(--line);border-radius:4px;padding:3px 5px;font:9px var(--mono);color:#728275}textarea{width:100%;border:1px solid #dfe5dc;border-radius:7px;background:#fafbf8;resize:vertical;min-height:100px;max-height:220px;padding:12px;font-size:13px;line-height:1.65;color:#3d4c40;margin-top:15px}textarea:focus{outline:none;border-color:#8ca89a}.preset-row{display:flex;gap:5px;margin-top:7px}.preset-row button{padding:3px 10px;border:1px solid var(--line);background:white;border-radius:4px;color:#7d877d;font-size:10px}.preset-row button:hover{border-color:#87a995;color:var(--green)}.settings{margin:17px 0 13px;font-size:11px;color:#7f8b80}.settings summary{cursor:pointer;display:flex;justify-content:space-between;list-style:none}.settings[open] summary{margin-bottom:10px}.setting-row{display:flex;align-items:center;justify-content:space-between;margin:7px 0}.setting-row input{width:83px;padding:5px;border:1px solid var(--line);border-radius:4px;font:11px var(--mono)}.primary{display:flex;width:100%;align-items:center;justify-content:center;gap:8px;background:var(--green);color:#fff;border:0;border-radius:6px;padding:11px;font-weight:500;font-size:12px}.primary span{font-size:17px}.stop-button{background:#fff;border:1px solid #c9d3ca;padding:10px;border-radius:6px;width:100%}.run-note{font-size:10px;line-height:1.5;color:#8e988e;margin:10px 0 0;min-height:15px}.terminal-section{display:flex;flex:1;flex-direction:column;min-height:180px;background:#1c2722;color:#cad7cb}.terminal-heading{padding:15px 18px;border-bottom:1px solid #344037}.terminal-heading h2{color:#647a6b}.terminal-heading h2 span{color:#c7d9c8}.terminal-heading>span{font:9px var(--mono);color:#8aab94}#terminal{flex:1;overflow:auto;padding:17px 18px;font:11px/1.9 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;max-height:410px}.terminal-welcome{color:#7d9583}.cursor{color:var(--lime);margin-left:3px;animation:blink 1.2s steps(1) infinite}.terminal-footer{border-top:1px solid #344037;padding:10px 18px;display:flex;align-items:center;justify-content:space-between;font:9px var(--mono);color:#819888}.terminal-footer button{border:0;color:#a5bda9;background:none;font-size:9px}.saved-section{padding:16px 18px 12px;height:119px;flex-shrink:0}.history{margin-top:10px;max-height:63px;overflow:auto}.history-row{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:5px 0;border:0;background:none;text-align:left;width:100%;font-size:10px;color:#6f7e71}.history-row span{font:9px var(--mono);margin-right:7px;color:#acb5a9}.muted{color:var(--muted);font-size:10px}.model-panel{display:flex;flex-direction:column;min-width:0;background:#fdfefb}.model-toolbar{display:flex;align-items:center;justify-content:space-between;padding:18px 20px 10px;gap:10px}.view-switch{display:flex;padding:3px;background:#f1f4ed;border-radius:5px}.view-switch button{border:0;background:none;color:#8c968a;font-size:10px;padding:5px 8px;border-radius:3px}.view-switch button.selected{background:#fff;color:var(--ink);box-shadow:0 1px 3px #182d1010}.map-legend{display:flex;gap:15px;justify-content:center;padding:10px 10px 1px;color:#85917f;font-size:9px}.swatch{display:inline-block;width:6px;height:6px;border-radius:2px;margin-right:4px}.full{background:#719ead}.sliding{background:#bccbbc}.active{background:#70ac52}.model-map{flex:1;position:relative;min-height:540px;margin:0 12px}#modelCanvas{display:block;width:100%;height:100%;cursor:crosshair}.map-tooltip{position:absolute;z-index:5;pointer-events:none;background:#203d30;color:#f2f9e9;box-shadow:0 3px 12px #18301c20;padding:9px 12px;max-width:260px;border-radius:5px;font:10px/1.6 var(--mono);white-space:pre-line}.model-footer{border-top:1px solid var(--line);font-size:9px;color:#8d9988;padding:10px 15px;display:flex;justify-content:space-between;align-items:center;gap:7px}.model-footer>span{display:flex;gap:5px;align-items:center}.status-dot{background:#699c66;width:5px;height:5px}.tiny-info{width:15px;height:15px;font-size:9px}.inspector-panel{padding:19px 18px 12px;border-left:1px solid var(--line);overflow:auto}.layer-nav{display:flex;gap:8px}.layer-nav button{border:1px solid var(--line);background:white;width:22px;height:21px;border-radius:4px;line-height:10px;font-size:17px}.layer-title{display:flex;justify-content:space-between;align-items:center;margin:17px 0 12px}h3{font-weight:500;font-size:22px;letter-spacing:-.6px;margin:0}.layer-title .small-tag{color:#61876b;background:#f4f8ed}.layer-flow{display:flex;flex-wrap:wrap;gap:4px;align-items:center;color:#8f9b8b;font:8px var(--mono);line-height:1.6}.layer-flow span:nth-child(3),.layer-flow span:nth-child(6){color:#526d56}.inspector-section{margin-top:23px}.inspector-heading{display:flex;align-items:center;justify-content:space-between;margin-bottom:11px;gap:5px}h4{margin:0;font-size:11px;font-weight:500}.inspector-heading>span{font:8px var(--mono);color:#8a9987}.head-grid{display:grid;grid-template-columns:repeat(8,1fr);gap:4px}.head{background:#edf1e8;border:1px solid transparent;border-radius:3px;aspect-ratio:1.25;color:#92a18c;font:9px var(--mono);padding:0}.head.selected{outline:1.5px solid var(--green);outline-offset:1px}.scale{display:flex;justify-content:space-between;align-items:center;gap:8px;color:#9ba795;font-size:8px;margin-top:9px}.scale i{height:4px;flex:1;background:linear-gradient(90deg,#e8f0d6,#96c992,#176b59);border-radius:2px}.head-reading{display:flex;justify-content:space-between;margin-top:12px;font:9px var(--mono);color:#86987e}.head-reading strong{font-weight:400;color:#4e6b4c}.expert-grid{display:grid;grid-template-columns:repeat(16,1fr);gap:3px}.expert{border:0;background:#eef1e9;aspect-ratio:1;border-radius:1px;padding:0;min-width:0}.expert.active{background:#79ad56}.expert.focused{outline:2px solid var(--green);outline-offset:1px}.expert-list{display:flex;flex-wrap:wrap;gap:5px;margin-top:11px}.expert-chip{background:#f0f5e9;border-radius:3px;padding:4px 5px;font:8px var(--mono);color:#5a7b47;white-space:nowrap}.expert-chip b{font-weight:500;margin-right:5px;color:#385e2d}.shared-expert{display:flex;align-items:center;gap:6px;border-top:1px solid var(--line);padding-top:11px;margin-top:11px;font-size:9px;color:#7d8d73}.shared-expert i{display:block;width:6px;height:6px;border-radius:2px;background:#e0e7d7}.shared-expert strong{font:8px var(--mono);margin-left:auto;color:#5a794e}.attention-list{display:flex;flex-direction:column;gap:6px}.attention-row{display:grid;grid-template-columns:28px minmax(0,1fr) 40px;gap:7px;font:9px var(--mono);align-items:center}.attention-row .pos{color:#9da994;font-size:8px}.attention-word{border-radius:2px;padding:3px 5px;white-space:pre;overflow:hidden;text-overflow:ellipsis;background:linear-gradient(90deg,#d9edcc var(--weight),#f4f7ef var(--weight));color:#536a48}.attention-row .weight{text-align:right;color:#618250;font-size:8px}.sink-note{font-size:8px;color:#97a18e;margin-top:4px}.playback{padding:16px 25px 12px}.playback-bar{display:flex;justify-content:space-between;align-items:center;gap:10px}.playback-controls,.playback-options{display:flex;align-items:center;gap:8px}.playback-controls button{background:white;border:1px solid #e0e6da;border-radius:4px;width:26px;height:26px;font-size:15px;padding:0}.playback-controls button:first-child{font-size:10px}.playback-controls>span{font:9px var(--mono);color:#77866e;margin-left:5px}.playback-options select{font-size:10px;background:transparent;border:0;color:#819076}.playback-options button{font-size:10px;background:none;border:1px solid #dfe5d8;border-radius:4px;padding:6px 9px;color:#7e8b75}#liveButton{display:flex;align-items:center;gap:6px}#liveButton i{width:5px;height:5px;border-radius:50%;background:#b5c0aa}#liveButton.live-selected{background:#eaf1df;color:#517238;border-color:#dce8cc}#liveButton.live-selected i{background:#71a446}#scrubber{width:100%;height:3px;accent-color:var(--green);margin:14px 0 11px;display:block}.token-strip{height:30px;display:flex;gap:4px;align-items:center;overflow-x:auto;scrollbar-width:thin}.token{background:#eaf0e0;border:1px solid transparent;font:10px var(--mono);border-radius:3px;padding:5px 7px;white-space:pre;flex-shrink:0;color:#6f815f}.token.selected{border-color:#668b52;background:#dcebca;color:#36582c}.token:hover{background:#dfeccb}dialog{border:1px solid var(--line);border-radius:12px;padding:34px;max-width:530px;color:var(--ink);box-shadow:0 20px 80px #15291a30}dialog::backdrop{background:#20332655;backdrop-filter:blur(3px)}dialog h2{font-size:24px;color:var(--ink);margin:15px 0 22px;letter-spacing:-.5px}dialog p{font-size:13px;line-height:1.75;color:#70806b}dialog a{color:var(--green);font-size:12px}.dialog-close{position:absolute;right:15px;top:10px;border:0;background:none;font-size:24px;color:#9da895}.toast{position:fixed;bottom:25px;left:50%;transform:translateX(-50%);background:#243b2a;color:#f0f6e8;box-shadow:0 4px 20px #172b1133;border-radius:6px;padding:12px 20px;z-index:10;max-width:90vw;font-size:12px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes blink{50%{opacity:0}}@media(min-height:1050px){main{min-height:700px}}@media(max-width:1200px){main{grid-template-columns:235px minmax(380px,1fr) 255px;margin:0 14px}.prompt-section{padding:16px 14px}.inspector-panel{padding:18px 13px}.stats{gap:24px}.overview{padding:23px 22px}.model-toolbar{padding:18px 13px 9px}.model-footer{font-size:8px;padding:10px}.map-legend{gap:8px;font-size:8px}header{padding:0 23px}.model-map{margin:0 5px}.head{font-size:8px}.expert-grid{gap:2px}}@media(max-width:980px){main{grid-template-columns:220px minmax(350px,1fr);height:auto;min-height:660px}.inspector-panel{grid-column:1/-1;border-left:0;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px 24px;padding:20px}.inspector-panel>.section-heading,.layer-title,.layer-flow{grid-column:1/-1;margin:0}.layer-flow{margin-bottom:4px}.inspector-section{margin-top:10px}.model-panel{min-height:660px}.stats{gap:20px}.stats strong{font-size:20px}.stats span{font-size:9px}h1{font-size:23px}.stats>div:last-child{display:none}}@media(max-width:650px){header{height:59px;padding:0 16px}.brand{font-size:20px;gap:8px}.brand b{font-size:16px}.brand-divider{margin:0 8px}.brand-icon{height:29px;width:27px;font-size:27px}.header-end{gap:10px}.engine-status{font-size:9px;max-width:108px}.overview{padding:23px 18px;display:block}.eyebrow{font-size:9px}h1{font-size:25px}.stats{margin-top:20px;justify-content:space-between;gap:10px}.stats strong{font-size:22px}.stats>div:last-child{display:flex}.stats>div:last-child strong{font-size:18px}.stats small{font-size:11px}.stats span{font-size:8px}main{display:flex;flex-direction:column;margin:0 10px;min-height:0}.input-panel{border-right:0}.prompt-section{padding:18px}.prompt-section textarea{min-height:85px;max-height:180px}.preset-row{margin-bottom:10px}.settings{margin:10px 0}.terminal-section{min-height:200px;max-height:320px}.saved-section{height:102px}.model-panel{border-top:1px solid var(--line);min-height:710px}.model-map{min-height:605px;margin:0 3px}.model-toolbar{padding:18px 13px 10px}.model-toolbar h2 span{font-size:11px}.map-legend{gap:12px;font-size:8px}.view-switch button{font-size:9px}.inspector-panel{display:block;padding:22px 18px}.inspector-panel>.section-heading{margin-bottom:15px}.layer-title{margin-bottom:10px}.inspector-section{margin-top:24px}.head{aspect-ratio:1.8}.expert-grid{gap:4px}.expert{aspect-ratio:1.5}.inspector-heading>span{font-size:9px}.attention-row{font-size:11px}.attention-row .weight{font-size:10px}.playback{padding:16px 13px}.playback-bar{align-items:flex-start;flex-direction:column;gap:12px}.playback-options{width:100%;justify-content:space-between}.playback-controls{width:100%}.playback-controls>span{margin-left:auto}.token-strip{height:42px}dialog{max-width:calc(100% - 28px);padding:28px 24px}.model-footer{font-size:8px}.stats>div{gap:4px}}
 
 
 
2
 
3
+ /* Fullscreen component inspection */
4
+ .open-block{font-size:22px;font-weight:500;letter-spacing:-.6px;border:0;padding:0;background:none;text-align:left}
5
+ .open-block:hover{color:var(--green)}
6
+ .layer-flow button{border:0;padding:0;background:none;color:#526d56;font:inherit;text-decoration:underline;text-underline-offset:3px}
7
+ button.shared-expert{width:100%;background:none;border:0;border-top:1px solid var(--line);text-align:left}
8
+ button.expert-chip{border:0}
9
+ .detail-open{overflow:hidden}
10
+ .detail-dialog{width:100vw;height:100dvh;max-width:none;max-height:none;inset:0;margin:0;padding:0;border:0;border-radius:0;background:var(--bg);box-shadow:none;overflow:hidden}
11
+ .detail-dialog[open]{display:flex;flex-direction:column}
12
+ .detail-header{display:flex;justify-content:space-between;gap:20px;align-items:center;padding:22px 36px 18px;background:#fff;border-bottom:1px solid var(--line);flex-shrink:0}
13
+ .detail-back{padding:0;border:0;background:none;font-size:11px;color:#7c8a7c}
14
+ .detail-dialog h2{margin:10px 0 8px;font-size:27px;font-weight:500;letter-spacing:-.8px}
15
+ .detail-subtitle{font-size:11px;color:#83917f;line-height:1.6}
16
+ .detail-navigation{display:flex;gap:8px;align-items:center}
17
+ .detail-navigation button{width:34px;height:34px;background:white;border:1px solid var(--line);border-radius:6px;font-size:24px;padding:0}
18
+ .detail-navigation button:last-child{margin-left:12px;background:#f2f5ee}
19
+ .detail-tabs{display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--line);padding:10px 36px;background:#fff;flex-shrink:0}
20
+ .detail-tabs button{border:0;border-radius:5px;padding:9px 16px;background:transparent;font-size:12px;color:#84907e}
21
+ .detail-tabs button.selected{background:#e7efdf;color:#365c39}
22
+ .detail-tabs>span{margin-left:auto;color:#7e8e76;font:10px var(--mono)}
23
+ .detail-body{flex:1;overflow:auto;padding:24px 36px 32px;min-height:0;scrollbar-width:thin}
24
+ .detail-body>*{max-width:1280px;margin-left:auto;margin-right:auto}
25
+ .detail-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;margin-bottom:24px}
26
+ .detail-stats>div{border-bottom:1px solid #dfe6d9;padding:0 0 15px;display:flex;flex-direction:column;gap:7px}
27
+ .detail-stats strong{font-size:26px;font-weight:500;letter-spacing:-.6px;overflow-wrap:anywhere}
28
+ .detail-stats span{font-size:11px;color:#83917b}
29
+ .detail-stats .is-active{color:var(--green)}
30
+ .detail-card{background:#fff;border:1px solid #e0e7d9;border-radius:10px;padding:20px;min-width:0}
31
+ .detail-card-heading{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:18px}
32
+ .detail-card h3{font-size:15px;letter-spacing:-.2px}
33
+ .detail-card-heading>span{font:10px var(--mono);color:#8b9b81}
34
+ .detail-card-heading b{font-weight:400}
35
+ .card-caption{font-size:10px;color:#8c9985;margin-top:16px;line-height:1.7}
36
+ .block-diagram{max-width:1120px}
37
+ .flow-pillar{display:flex;justify-content:space-between;align-items:center;max-width:430px;margin:0 auto;background:#e8efdf;border:1px solid #dbe5d0;border-radius:7px;padding:12px 20px;color:#526c42;font-size:12px}
38
+ .flow-pillar b{font:12px var(--mono)}
39
+ .flow-connector{display:flex;flex-direction:column;align-items:center;gap:7px;padding:12px;color:#90a17f;font-size:15px}
40
+ .flow-connector span{font:10px var(--mono);color:#7b8f69}
41
+ .detail-head-grid{display:grid;grid-template-columns:repeat(16,minmax(0,1fr));gap:6px}
42
+ .detail-head{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:5px;min-width:0;height:100px;border:1px solid #dce6d1;background:#edf2e5;border-radius:5px;overflow:hidden;padding:9px 3px;color:#284b35}
43
+ .detail-head b{font:12px var(--mono);z-index:1;font-weight:500}
44
+ .detail-head small{font:9px var(--mono);z-index:1;opacity:.8}
45
+ .head-meter{position:absolute;width:calc(100% - 12px);height:var(--level,0%);max-height:100%;bottom:0;background:#fff3;pointer-events:none;border-top:1px solid #fff7}
46
+ .detail-head.selected,.detail-expert.selected,.route-card.selected{outline:2px solid var(--green);outline-offset:2px}
47
+ .detail-head:hover,.detail-expert:hover,.route-card:hover{box-shadow:0 0 0 2px #9bb68a}
48
+ .detail-head-grid.compact{grid-template-columns:repeat(8,minmax(0,1fr))}
49
+ .detail-head-grid.compact .detail-head{height:72px}
50
+ .route-cards{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px}
51
+ .route-card{position:relative;border:1px solid #dce8d0;background:#eff5e7;border-radius:6px;padding:12px;min-width:0;text-align:left;display:flex;flex-direction:column;gap:10px;overflow:hidden;color:#426536}
52
+ .route-card span{font:10px var(--mono);white-space:nowrap}
53
+ .route-card strong{font-size:19px;font-weight:500}
54
+ .route-card i{height:3px;width:var(--weight);background:#6d9c4e;display:block;min-width:1px}
55
+ .route-cards.vertical{grid-template-columns:repeat(2,minmax(0,1fr))}
56
+ .route-cards.vertical .route-card{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between}
57
+ .route-cards.vertical .route-card strong{font:12px var(--mono)}
58
+ .route-cards.vertical .route-card i{flex-basis:var(--weight)}
59
+ .expert-map-heading{display:flex;align-items:center;justify-content:space-between;margin:23px 0 12px;font:10px var(--mono);color:#829273;gap:12px}
60
+ .shared-detail-link{border:1px solid #dde7d3;background:#f6f9f0;border-radius:4px;padding:7px 10px;font:10px var(--mono);color:#557643}
61
+ .detail-expert-grid{display:grid;grid-template-columns:repeat(32,minmax(0,1fr));gap:4px}
62
+ .detail-expert{min-width:0;padding:5px 0;height:27px;font:8px var(--mono);border-radius:3px;background:#f0f3eb;border:1px solid #e5ebde;color:#8c9b80}
63
+ .detail-expert.routed{border-color:#719a5c;color:#183b28}
64
+ .detail-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px;margin-bottom:20px}
65
+ .detail-columns .detail-expert-grid{grid-template-columns:repeat(16,minmax(0,1fr));gap:4px}
66
+ .component-selector{display:flex;align-items:center;gap:12px;margin-bottom:22px}
67
+ .component-selector label{font-size:12px;color:#75876b}
68
+ .component-selector select{border:1px solid #d6e2cb;border-radius:5px;background:white;padding:7px 30px 7px 10px;color:#3d5c33;font:12px var(--mono)}
69
+ .component-selector>span{color:#8e9b86;font:10px var(--mono);line-height:1.6}
70
+ .component-circuit{display:flex;align-items:center;justify-content:center;gap:12px;margin-top:22px;margin-bottom:26px}
71
+ .circuit-node{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:22px 16px;min-height:92px;flex:1;max-width:260px;background:#ebf1e3;border:1px solid #dce5d1;border-radius:9px;text-align:center}
72
+ .circuit-node strong{font-size:19px;font-weight:500;letter-spacing:-.3px}
73
+ .circuit-node span{font:10px/1.6 var(--mono);color:#839774}
74
+ .circuit-link{display:flex;flex-direction:column;align-items:center;gap:7px;color:#80936e;flex-shrink:0}
75
+ .circuit-link span{font:9px var(--mono)}
76
+ .circuit-link b{font-size:21px;font-weight:400}
77
+ .expert-core.engaged{background:#d0e6ba;border-color:#8eae77;color:#325728}
78
+ .detail-attention-rows{display:flex;flex-direction:column;gap:8px}
79
+ .detail-attention-row{display:grid;grid-template-columns:52px minmax(0,1fr) 65px;gap:12px;align-items:center;font:11px var(--mono)}
80
+ .attention-position{font-size:10px;color:#94a089}
81
+ .detail-attention-row code{padding:10px 12px;border-radius:4px;overflow:hidden;text-overflow:ellipsis;white-space:pre;background:linear-gradient(90deg,#d4e7c1 var(--weight),#f3f6ed var(--weight));color:#4e6840;font:12px var(--mono)}
82
+ .detail-attention-row strong{font:11px var(--mono);text-align:right;color:#6a8657}
83
+ .attention-mass{display:flex;flex-wrap:wrap;gap:8px 22px;border-top:1px solid var(--line);padding-top:14px;margin-top:16px;font:10px/1.6 var(--mono);color:#8a9b7d}
84
+ .mixture-readings{border-top:1px solid var(--line);margin-top:18px;padding-top:14px;display:flex;gap:12px;flex-wrap:wrap;justify-content:space-between;font-size:10px;color:#7e8f72}
85
+ .mixture-readings b{font:10px var(--mono);font-weight:400;color:#527242;margin-left:6px}
86
+ .mixture-readings button{padding:0;background:none;border:0;font-size:10px;color:#7e8f72}
87
+ .detail-timeline{display:flex;gap:5px;min-height:133px;overflow-x:auto;scrollbar-width:thin;padding:4px 3px 10px;align-items:stretch}
88
+ .timeline-token{width:36px;min-width:36px;background:#f4f7ee;border:1px solid transparent;border-radius:4px;position:relative;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;gap:7px;padding:8px 2px;color:#5b7748;overflow:hidden}
89
+ .timeline-bar{position:absolute;bottom:43px;width:20px;height:calc(var(--level,0%) * .58);background:#8bb66a;border-radius:2px 2px 0 0}
90
+ .timeline-token code{font:9px var(--mono);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:pre;margin-top:78px}
91
+ .timeline-token small{font:8px var(--mono);color:#9aa78e}
92
+ .timeline-token.selected{border-color:#4e7e3d;background:#e7f0da}
93
+ .timeline-token.inactive{background:#f5f6f2;color:#a4ae9c}
94
+ .timeline-token:hover{border-color:#9cb88b}
95
+ .detail-empty{font-size:12px;color:#91a087;line-height:1.7;padding:14px 0}
96
+ .detail-playback{flex-shrink:0;border-top:1px solid #dce5d3;padding:14px 36px 16px;background:#fff}
97
+ .detail-token-context{display:flex;align-items:center;gap:14px;margin-bottom:12px;min-width:0}
98
+ .detail-token-context>span{font:10px var(--mono);color:#7e9070;white-space:nowrap}
99
+ .detail-token-context code{padding:5px 9px;background:#edf3e4;border-radius:3px;font:12px var(--mono);white-space:pre;overflow:hidden;text-overflow:ellipsis;color:#426034;max-width:55%}
100
+ .detail-token-context>span:last-child{margin-left:auto;font-size:9px}
101
+ .detail-control-row{display:flex;align-items:center;gap:16px}
102
+ .detail-control-row .playback-controls button{width:30px;height:30px}
103
+ .detail-speed{display:flex;gap:7px;align-items:center;font-size:10px;color:#839474}
104
+ .detail-speed select{border:1px solid #dde6d4;border-radius:4px;background:#f7f9f3;padding:7px;color:#476838;font-size:11px}
105
+ .detail-live{background:white;border:1px solid #dce6d0;border-radius:4px;padding:7px 11px;color:#849578;font-size:10px}
106
+ .detail-live.selected{background:#e9f1df;color:#4f7337}
107
+ #detailPlaybackNote{font-size:10px;color:#94a187;margin-left:auto}
108
+ #detailScrubber{display:block;width:100%;height:3px;margin:15px 0 0;accent-color:var(--green)}
109
+ @media(min-width:1600px){.detail-body{padding-top:32px}.detail-head{height:115px}}
110
+ @media(max-width:900px){.detail-header{padding:18px 22px}.detail-tabs{padding:9px 22px}.detail-body{padding:22px}.detail-playback{padding:13px 22px 17px}.detail-stats strong{font-size:22px}.detail-head-grid{grid-template-columns:repeat(8,minmax(0,1fr))}.detail-head{height:80px}.detail-expert-grid{grid-template-columns:repeat(16,minmax(0,1fr))}.route-cards{grid-template-columns:repeat(3,minmax(0,1fr))}.detail-columns{grid-template-columns:minmax(0,1fr)}.detail-columns .detail-expert-grid{grid-template-columns:repeat(16,minmax(0,1fr))}.component-circuit{gap:8px}.circuit-node{padding:17px 10px}.circuit-node strong{font-size:17px}.circuit-node span{font-size:8px}.circuit-link span{font-size:8px}.component-selector>span{margin-left:auto;max-width:50%;font-size:9px}}
111
+ @media(max-width:550px){.detail-header{padding:15px 16px 13px;gap:10px;align-items:flex-start}.detail-dialog h2{font-size:21px;margin:9px 0 6px}.detail-subtitle{font-size:9px}.detail-navigation{gap:5px}.detail-navigation button{width:28px;height:28px;font-size:20px}.detail-navigation button:last-child{margin-left:0}.detail-back{font-size:10px}.detail-tabs{padding:8px 12px;gap:3px;flex-wrap:wrap}.detail-tabs button{padding:8px 12px;font-size:11px}.detail-tabs>span{font-size:8px}.detail-body{padding:18px 14px 24px}.detail-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:20px}.detail-stats strong{font-size:22px}.detail-stats span{font-size:10px}.detail-stats>div{padding-bottom:10px}.detail-card{padding:15px 12px;border-radius:8px}.detail-card h3{font-size:13px}.detail-card-heading>span{font-size:8px}.detail-head-grid{gap:5px}.detail-head{height:69px}.detail-head b{font-size:10px}.detail-head small{font-size:7px}.route-cards{gap:6px}.route-card{padding:9px 8px;gap:7px}.route-card span{font-size:8px}.route-card strong{font-size:17px}.route-cards.vertical .route-card strong{font-size:10px}.detail-expert-grid,.detail-columns .detail-expert-grid{gap:3px}.detail-expert{font-size:7px;height:22px;padding:0}.expert-map-heading{font-size:9px;gap:7px}.shared-detail-link{font-size:8px;padding:6px}.component-selector{gap:8px;flex-wrap:wrap}.component-selector label{font-size:11px}.component-selector select{font-size:10px;max-width:150px}.component-selector>span{max-width:none;flex-basis:100%;margin:0}.component-circuit{flex-wrap:wrap;gap:7px;margin-top:10px;margin-bottom:20px}.circuit-node{padding:14px 8px;min-height:78px;min-width:75px}.circuit-node strong{font-size:14px}.circuit-node span{font-size:8px}.circuit-link span{max-width:46px;text-align:center;font-size:7px}.circuit-link b{font-size:17px}.expert-circuit .circuit-link{max-width:35px}.expert-circuit .circuit-node{flex:0 1 25%}.expert-circuit .circuit-node:last-child{flex:1 0 100%;max-width:none;min-height:64px;margin-top:3px}.detail-attention-row{grid-template-columns:37px minmax(0,1fr) 48px;gap:8px}.detail-attention-row code{font-size:11px;padding:9px}.detail-attention-row strong{font-size:10px}.attention-position{font-size:9px}.attention-mass{font-size:9px}.detail-playback{padding:12px 14px max(14px,env(safe-area-inset-bottom))}.detail-token-context{gap:8px;margin-bottom:10px;flex-wrap:wrap}.detail-token-context>span{font-size:9px}.detail-token-context>span:last-child{font-size:8px}.detail-token-context code{font-size:10px;max-width:45%}.detail-control-row{gap:10px;flex-wrap:wrap}.detail-control-row .playback-controls{width:auto;gap:5px}.detail-control-row .playback-controls button{width:29px;height:29px}.detail-speed{font-size:9px;gap:5px}.detail-speed select{font-size:10px;max-width:116px;padding:6px}.detail-live{font-size:9px;padding:7px 8px;margin-left:auto}#detailPlaybackNote{width:100%;margin:0;font-size:9px}#detailScrubber{margin-top:12px}}
112
 
113
+ /* Model selection and recurrent attention */
114
+ .models-header{height:auto;min-height:76px;gap:24px;padding-top:12px;padding-bottom:12px}
115
+ .header-start{display:flex;align-items:center;gap:32px;min-width:0}
116
+ .model-control{display:flex;align-items:center;gap:10px}
117
+ .model-control>span{font:9px var(--mono);letter-spacing:1px;color:#8a9781}
118
+ .model-control select{border:1px solid #dce4d5;background:#f7f9f3;border-radius:6px;padding:9px 30px 9px 12px;color:#34553b;font-size:12px;min-width:176px;max-width:240px}
119
+ .model-control select:disabled{opacity:.6}
120
+ .brand-icon{font-style:normal;font-size:25px}
121
+ .linear{background:#8fa99d}
122
+ .dense-inspect{padding:8px 10px;background:#f1f5e9;border:1px solid #e0e8d5;border-radius:4px;font:9px var(--mono);color:#60804d;text-align:left}
123
+ .recurrent-reading{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px solid #edf1e7;font-size:10px;color:#8a9b7c}
124
+ .recurrent-reading strong{font:11px var(--mono);color:#4d7040;font-weight:400}
125
+ .recurrent-note{font-size:10px;line-height:1.7;color:#92a085;margin:10px 0 0}
126
+ .detail-recurrent{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
127
+ .memory-metric{border:1px solid #dfE8d5;border-radius:8px;background:#f4f8ee;padding:20px 16px;display:flex;flex-direction:column;gap:10px}
128
+ .memory-metric strong{font-size:25px;font-weight:500;color:#3d653a}
129
+ .memory-metric span{font:10px var(--mono);color:#8b9d7a}
130
+ .memory-meter{height:5px;background:#e1ebd6;border-radius:3px;overflow:hidden}
131
+ .memory-meter i{display:block;height:100%;background:#81ab63;width:var(--value,0%)}
132
+ .recurrent-explanation{font-size:12px!important;line-height:1.8!important;color:#809271!important;margin:18px 0 0!important}
133
+ .timeline-metric-select{font:10px var(--mono);border:1px solid #dce6d1;background:#f8faf4;padding:5px 8px;border-radius:4px;color:#6a8459}
134
+ .ffn-output{margin-top:20px;font:12px var(--mono);color:#618450;text-align:center}
135
+ @media(max-width:1000px){.header-start{gap:18px}.model-control>span{display:none}.model-control select{min-width:158px;font-size:11px}.models-header{gap:15px}.brand{font-size:21px}.brand b{font-size:17px}}
136
+ @media(max-width:650px){.models-header{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;padding:14px 16px}.header-start{display:contents}.header-start>.brand{grid-column:1;grid-row:1}.models-header>.header-end{grid-column:2;grid-row:1}.model-control{grid-column:1/-1;grid-row:2;gap:14px}.model-control>span{display:block;font-size:8px}.model-control select{max-width:none;min-width:0;width:100%;font-size:12px;padding:9px 12px}.models-header .brand{font-size:19px}.models-header .brand b{font-size:15px}.models-header .brand-divider{margin:0 7px}.models-header .brand-icon{width:25px;height:28px;font-size:22px}.models-header .engine-status{font-size:8px;max-width:90px}.models-header .header-end{gap:8px}.detail-recurrent{grid-template-columns:minmax(0,1fr)}.memory-metric{padding:15px}.memory-metric strong{font-size:23px}.recurrent-reading{font-size:11px}.recurrent-reading strong{font-size:12px}}
137
 
138
+ /* Public capture viewer */
139
+ .trace-origin{font:11px var(--mono);color:#527461;margin:14px 0 10px}.capture-settings{font-size:10px;line-height:1.7;color:#687d6f;margin:10px 0 16px}.prompt-section textarea[readonly]{background:#f5f8f1;cursor:text}.capture-help{font-size:11px;line-height:1.7;margin-top:14px;color:#526d5e}.capture-help summary{cursor:pointer}.capture-help p{margin:10px 0}.capture-help a{color:var(--green)}.site-footer{display:flex;align-items:center;justify-content:center;gap:20px;flex-wrap:wrap;padding:22px 18px 28px;font-size:11px;color:#61746a}.site-footer a{color:var(--green);text-decoration:none}.site-footer a:first-child{font-weight:700}.site-footer a:hover{text-decoration:underline}.run-note{min-height:32px}.model-map:focus-within{outline:2px solid var(--green);outline-offset:-2px}.engine-status{cursor:default}.history-row{text-align:left}.capture-help summary:focus-visible{outline:2px solid var(--green);outline-offset:3px}
140
+ @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;scroll-behavior:auto!important}}
141
+ @media(max-width:650px){.site-footer{gap:14px}.site-footer>span{flex-basis:100%;text-align:center;order:4}.run-note{min-height:0}.capture-help{font-size:12px}.overview h1{font-size:28px}.engine-status{max-width:100px!important}}
142
+ @media(max-width:650px){.models-header .header-end{display:contents}.models-header .engine-status{grid-column:1/-1;grid-row:3;justify-self:start;max-width:none!important;font-size:10px}.models-header #aboutButton{grid-column:2;grid-row:1}.model-panel{order:0;border-top:0}.input-panel{order:1;border-top:1px solid var(--line)}.inspector-panel{order:2}.model-toolbar{padding-top:20px}.model-footer{gap:8px;line-height:1.5;align-items:flex-start}.model-footer>span{min-width:0}.stats>div:last-child strong{font-size:17px}.stats{align-items:flex-start}.stats>div{min-width:0;max-width:27%}}
 
 
 
 
 
 
tests/release.test.cjs ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+ const test=require('node:test');
3
+ const assert=require('node:assert/strict');
4
+ const fs=require('node:fs');
5
+ const path=require('node:path');
6
+ const zlib=require('node:zlib');
7
+ const crypto=require('node:crypto');
8
+ const root=path.resolve(__dirname,'..');
9
+ const digest=b=>crypto.createHash('sha256').update(b).digest('hex');
10
+ const rows=JSON.parse(fs.readFileSync(path.join(root,'traces/index.json')));
11
+ for(const row of rows){
12
+ test(row.model+' capture matches both published checksums and exact frame count',()=>{
13
+ const compressed=fs.readFileSync(path.join(root,row.file)),plain=zlib.gunzipSync(compressed),trace=JSON.parse(plain);
14
+ assert.equal(digest(compressed),row.gzip_sha256);assert.equal(digest(plain),row.sha256);
15
+ assert.equal(plain.length,row.bytes);assert.equal(compressed.length,row.compressed_bytes);
16
+ assert.equal(trace.id,row.id);assert.equal(trace.model.id,row.model);assert.equal(trace.frames.length,row.tokens);
17
+ assert.equal(trace.prompt,row.prompt);assert.equal(trace.result.reason,'eos');
18
+ });
19
+ }
20
+ test('the examples share the same original prompt and sampling settings',()=>{
21
+ const traces=rows.map(row=>JSON.parse(zlib.gunzipSync(fs.readFileSync(path.join(root,row.file)))));
22
+ assert.equal(traces[0].prompt,traces[1].prompt);assert.deepEqual(traces[0].settings,traces[1].settings);
23
+ assert.equal(traces.reduce((n,t)=>n+t.frames.length,0),103);
24
+ });
25
+ test('the static entry point references files included in the release',()=>{
26
+ const html=fs.readFileSync(path.join(root,'index.html'),'utf8');
27
+ for(const [,file]of html.matchAll(/(?:src|href)="([^"?#]+\.(?:js|css|svg))"/g))assert.ok(fs.statSync(path.join(root,file)).isFile(),file);
28
+ for(const name of ['README.md','TRACE-FORMAT.md','NOTICE','LICENSE','cover.png','preview.png','sources.json'])assert.ok(fs.statSync(path.join(root,name)).size>0,name);
29
+ });
30
+ test('the viewer has no inference or third-party font dependency',()=>{
31
+ const app=fs.readFileSync(path.join(root,'app.js'),'utf8'),css=fs.readFileSync(path.join(root,'style.css'),'utf8');
32
+ assert.doesNotMatch(app,/new EventSource|fetch\(['"]api\//);assert.doesNotMatch(css,/@import|https?:\/\//);
33
+ });
tests/trace-validation.test.cjs ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict';
2
+ const test = require('node:test');
3
+ const assert = require('node:assert/strict');
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const zlib = require('node:zlib');
7
+ const vm = require('node:vm');
8
+ const { validateObservatoryTrace } = require('../trace-validation.js');
9
+ const root = path.resolve(__dirname, '..');
10
+ const models = JSON.parse(fs.readFileSync(path.join(root, 'models.json'), 'utf8'));
11
+ const readTrace = id => JSON.parse(zlib.gunzipSync(fs.readFileSync(path.join(root, 'traces', id + '-sky-q8.json.gz'))));
12
+ const captures = { flint: readTrace('flint'), qwen: readTrace('qwen') };
13
+ // Invalid-input tests change small copies of real captured frames. The distributed
14
+ // captures remain untouched, and these changes are never presented as activations.
15
+ function sample(id = 'flint') {
16
+ const original = captures[id];
17
+ return structuredClone({ ...original, frames: original.frames.slice(0, 2) });
18
+ }
19
+ function rejects(title, mutate, id = 'flint') {
20
+ test(title, () => {
21
+ const trace = sample(id);
22
+ mutate(trace);
23
+ assert.throws(() => validateObservatoryTrace(trace, models), Error);
24
+ });
25
+ }
26
+ for (const id of ['flint', 'qwen']) {
27
+ test('accepts every real ' + id + ' frame without changing the source', () => {
28
+ const trace = captures[id];
29
+ const before = JSON.stringify(trace);
30
+ assert.equal(validateObservatoryTrace(trace, models), models.find(model => model.id === id));
31
+ assert.equal(JSON.stringify(trace), before);
32
+ });
33
+ }
34
+ test('accepts legacy Flint traces without model metadata or token bytes', () => {
35
+ const trace = sample();
36
+ delete trace.model;
37
+ for (const frame of trace.frames) { delete frame.model; delete frame.token_bytes; }
38
+ assert.equal(validateObservatoryTrace(trace, models).id, 'flint');
39
+ });
40
+ test('accepts a stopped capture that retains its measured frames', () => {
41
+ const trace = sample();
42
+ trace.result.reason = 'stopped';
43
+ assert.equal(validateObservatoryTrace(trace, models).id, 'flint');
44
+ });
45
+ test('accepts floating point probability roundoff within capture precision', () => {
46
+ const trace = sample('qwen');
47
+ trace.frames[0].layers[0].retention[0] = 1 + 0.000001;
48
+ assert.equal(validateObservatoryTrace(trace, models).id, 'qwen');
49
+ });
50
+ test('exports the browser validator without requiring Node globals', () => {
51
+ const context = {};
52
+ vm.runInNewContext(fs.readFileSync(path.join(root, 'trace-validation.js'), 'utf8'), context);
53
+ assert.equal(context.validateObservatoryTrace(sample(), models).id, 'flint');
54
+ });
55
+ rejects('rejects model metadata that contradicts the schema', t => { t.model.id = 'qwen'; });
56
+ rejects('rejects unrecognized trace schema', t => { t.schema = 'arbitrary.v1'; });
57
+ rejects('rejects empty captures', t => { t.frames = []; });
58
+ rejects('rejects excessive frame counts', t => { t.frames = Array(257).fill(t.frames[0]); });
59
+ rejects('rejects wrong full-attention dimensions', t => { t.architecture.head_dim++; });
60
+ rejects('rejects mismatched expert pool dimensions', t => { t.architecture.num_experts = 128; });
61
+ rejects('rejects mismatched expert feed-forward width', t => { t.architecture.moe_intermediate_size++; });
62
+ rejects('rejects changed dense layer assignments', t => { t.architecture.mlp_only_layers = [0]; });
63
+ rejects('rejects changed sliding-window size', t => { t.architecture.sliding_window++; });
64
+ rejects('rejects recurrent key-head dimension mismatch', t => { t.architecture.linear_key_head_dim++; }, 'qwen');
65
+ rejects('rejects recurrent value-head count mismatch', t => { t.architecture.linear_num_value_heads++; }, 'qwen');
66
+ rejects('rejects quantization mismatches', t => { t.model.quantization = 'Q4_0'; });
67
+ rejects('rejects malformed prompt tokens', t => { t.start.tokens[0] = {}; });
68
+ rejects('rejects excessive prompt-token counts', t => { t.start.tokens = Array(2049).fill('x'); });
69
+ rejects('rejects oversized individual token strings', t => { t.start.tokens[0] = 'x'.repeat(8193); });
70
+ rejects('rejects inconsistent declared prompt length', t => { t.start.prompt_tokens++; });
71
+ rejects('rejects oversized prompts', t => { t.prompt = 'x'.repeat(4001); });
72
+ rejects('rejects invalid generation settings', t => { t.settings.seed = -1; });
73
+ rejects('rejects non-boolean reasoning settings', t => { t.settings.reasoning = 'false'; });
74
+ rejects('rejects invalid temperature', t => { t.settings.temperature = Infinity; });
75
+ rejects('rejects model changes inside captured frames', t => { t.frames[0].model = 'qwen'; });
76
+ rejects('rejects inconsistent frame positions', t => { t.frames[0].input_position++; });
77
+ rejects('rejects reordered token steps', t => { t.frames[1].step = 0; });
78
+ rejects('rejects negative token IDs', t => { t.frames[0].token_id = -1; });
79
+ rejects('rejects out-of-vocabulary token IDs', t => { t.frames[0].token_id = t.architecture.vocab_size; });
80
+ rejects('rejects invalid raw token bytes', t => { t.frames[0].token_bytes = [256]; });
81
+ rejects('rejects fractional raw token bytes', t => { t.frames[0].token_bytes = [1.5]; });
82
+ rejects('rejects null raw token byte arrays', t => { t.frames[0].token_bytes = null; });
83
+ rejects('rejects nonfinite timings', t => { t.frames[0].duration = NaN; });
84
+ rejects('rejects elapsed time moving backwards', t => { t.frames[1].elapsed = 0; });
85
+ rejects('rejects missing layers', t => { t.frames[0].layers.pop(); });
86
+ rejects('rejects missing head measurements', t => { t.frames[0].layers[0].heads.pop(); });
87
+ rejects('rejects NaN output magnitudes', t => { t.frames[0].layers[0].heads[0] = NaN; });
88
+ rejects('rejects infinite residual output', t => { t.frames[0].layers[0].residual = Infinity; });
89
+ rejects('rejects negative feed-forward output', t => { t.frames[0].layers[0].ffn = -1; });
90
+ rejects('rejects inconsistent layer indices', t => { t.frames[0].layers[0].index = 1; });
91
+ rejects('rejects repeated expert selections', t => { t.frames[0].layers[2].experts[0] = t.frames[0].layers[2].experts[1]; });
92
+ rejects('rejects expert IDs outside the pool', t => { t.frames[0].layers[2].experts[0] = 256; });
93
+ rejects('rejects non-normalized expert weights', t => { t.frames[0].layers[2].weights[0] = 0; });
94
+ rejects('rejects missing shared expert measurements', t => { delete t.frames[0].layers[2].shared; });
95
+ rejects('rejects nonfinite routed output', t => { t.frames[0].layers[2].routed = Infinity; });
96
+ rejects('rejects missing recurrent state measurements', t => { delete t.frames[0].layers[0].state_rms; }, 'qwen');
97
+ rejects('rejects invalid recurrent retention probability', t => { t.frames[0].layers[0].retention[0] = 1.01; }, 'qwen');
98
+ rejects('rejects negative recurrent write gate', t => { t.frames[0].layers[0].write_gate[0] = -0.1; }, 'qwen');
99
+ rejects('rejects wrong attention head count', t => { t.frames[0].layers[0].attention.pop(); });
100
+ rejects('rejects invalid attention entropy', t => { t.frames[0].layers[0].attention[0].entropy = Infinity; });
101
+ rejects('rejects invalid learned sink probability', t => { t.frames[0].layers[0].attention[0].sink = 1.1; });
102
+ rejects('rejects attention to positions in the future', t => { t.frames[0].layers[0].attention[0].top[0][0] = 2047; });
103
+ rejects('rejects repeated attention positions', t => { const a = t.frames[0].layers[0].attention[0]; a.top[0][0] = a.top[1][0]; });
104
+ rejects('rejects attention probability mass exceeding one', t => { t.frames[0].layers[0].attention[0].top[0][1] = 1; });
105
+ test('failed validation does not change a previously selected capture', () => {
106
+ const loaded = { model: models[0], trace: captures.flint };
107
+ const previous = { ...loaded };
108
+ const candidate = sample('qwen');
109
+ candidate.frames[0].layers[0].heads = [];
110
+ assert.throws(() => {
111
+ const model = validateObservatoryTrace(candidate, models);
112
+ loaded.model = model;
113
+ loaded.trace = candidate;
114
+ });
115
+ assert.equal(loaded.model, previous.model);
116
+ assert.equal(loaded.trace, previous.trace);
117
+ });
trace-validation.js ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* alphaBell Model Observatory trace import checks. No data is changed here. */
2
+ (function (root) {
3
+ 'use strict';
4
+ const LIMITS = Object.freeze({ frames: 256, context: 2048, tokenText: 8192, prompt: 4000 });
5
+ const EPSILON = 0.00001;
6
+ const object = value => value !== null && typeof value === 'object' && !Array.isArray(value);
7
+ const number = value => typeof value === 'number' && Number.isFinite(value);
8
+ const nonnegative = value => number(value) && value >= 0;
9
+ const probability = value => nonnegative(value) && value <= 1 + EPSILON;
10
+ const integer = (value, minimum, maximum) => Number.isInteger(value) && value >= minimum && value <= maximum;
11
+ const text = value => typeof value === 'string' && value.length <= LIMITS.tokenText;
12
+ function requireValue(condition, message) {
13
+ if (!condition) throw new Error(message);
14
+ }
15
+ function vector(value, length, predicate, message) {
16
+ requireValue(Array.isArray(value) && value.length === length && value.every(predicate), message);
17
+ }
18
+ function validateObservatoryTrace(d, models) {
19
+ requireValue(object(d) && Array.isArray(models), 'This file is not a supported model trace.');
20
+ requireValue(['flint.trace.v1', 'model.trace.v1'].includes(d.schema), 'This file is not a supported model trace.');
21
+ const id = d.model?.id || (d.schema === 'flint.trace.v1' ? 'flint' : null);
22
+ const model = models.find(item => item.id === id);
23
+ requireValue(Boolean(model) && (d.schema !== 'flint.trace.v1' || id === 'flint'), 'The trace identifies an unsupported model.');
24
+ const c = model.architecture;
25
+ requireValue(object(c) && object(d.architecture), 'The trace has no supported architecture.');
26
+ const requiredKeys = [
27
+ 'num_hidden_layers', 'num_attention_heads', 'num_key_value_heads', 'hidden_size',
28
+ 'head_dim', 'intermediate_size', 'layer_types'
29
+ ];
30
+ const defaultZero = ['num_experts', 'num_experts_per_tok', 'first_k_dense_replace'];
31
+ const defaultArray = ['mlp_only_layers', 'no_rope_layer_indices'];
32
+ const conditionalKeys = [
33
+ 'sliding_window', 'moe_intermediate_size', 'shared_expert_intermediate_size',
34
+ 'linear_num_key_heads', 'linear_num_value_heads', 'linear_key_head_dim', 'linear_value_head_dim'
35
+ ];
36
+ const mismatch = 'The trace architecture does not match ' + model.short_name + '.';
37
+ for (const key of requiredKeys) {
38
+ requireValue(JSON.stringify(d.architecture[key]) === JSON.stringify(c[key]), mismatch);
39
+ }
40
+ for (const key of defaultZero) requireValue((d.architecture[key] ?? 0) === (c[key] ?? 0), mismatch);
41
+ for (const key of defaultArray) {
42
+ requireValue(JSON.stringify(d.architecture[key] ?? []) === JSON.stringify(c[key] ?? []), mismatch);
43
+ }
44
+ for (const key of conditionalKeys) {
45
+ if (c[key] !== undefined) requireValue(d.architecture[key] === c[key], mismatch);
46
+ }
47
+ if (d.model?.quantization !== undefined) {
48
+ requireValue(d.model.quantization === model.quantization, 'The trace quantization does not match the selected model.');
49
+ }
50
+ requireValue(Array.isArray(d.frames) && d.frames.length > 0 && d.frames.length <= LIMITS.frames,
51
+ 'The trace must contain between 1 and 256 measured frames.');
52
+ requireValue(object(d.start) && Array.isArray(d.start.tokens) && d.start.tokens.length > 0 &&
53
+ d.start.tokens.length <= LIMITS.context && d.start.tokens.every(text), 'The trace has invalid prompt tokens.');
54
+ if (d.start.prompt_tokens !== undefined) {
55
+ requireValue(d.start.prompt_tokens === d.start.tokens.length, 'The trace prompt-token count is inconsistent.');
56
+ }
57
+ if (d.prompt !== undefined) {
58
+ requireValue(typeof d.prompt === 'string' && d.prompt.length <= LIMITS.prompt, 'The trace prompt is invalid.');
59
+ }
60
+ if (d.settings !== undefined) {
61
+ requireValue(object(d.settings), 'The trace settings are invalid.');
62
+ const settings = d.settings;
63
+ if (settings.max_tokens !== undefined) requireValue(integer(settings.max_tokens, 1, LIMITS.frames), 'The output limit is invalid.');
64
+ if (settings.temperature !== undefined) requireValue(nonnegative(settings.temperature) && settings.temperature <= 1.5, 'The temperature is invalid.');
65
+ if (settings.seed !== undefined) requireValue(integer(settings.seed, 0, 2147483647), 'The seed is invalid.');
66
+ if (settings.reasoning !== undefined) requireValue(typeof settings.reasoning === 'boolean', 'The reasoning setting is invalid.');
67
+ }
68
+ let previousElapsed = -1;
69
+ for (let frameIndex = 0; frameIndex < d.frames.length; frameIndex++) {
70
+ const f = d.frames[frameIndex];
71
+ requireValue(object(f) && text(f.text), 'The trace contains invalid token text.');
72
+ requireValue(integer(f.input_position, 0, LIMITS.context - 1) &&
73
+ f.input_position === d.start.tokens.length - 1 + frameIndex, 'The trace input position is inconsistent.');
74
+ if (f.model !== undefined) requireValue(f.model === id, 'A trace frame identifies a different model.');
75
+ if (f.step !== undefined) requireValue(f.step === frameIndex, 'The trace token order is inconsistent.');
76
+ requireValue(integer(f.token_id, 0, (c.vocab_size || Number.MAX_SAFE_INTEGER) - 1), 'The trace contains an invalid token ID.');
77
+ requireValue(nonnegative(f.duration) && nonnegative(f.elapsed) && f.elapsed >= previousElapsed,
78
+ 'The trace contains invalid token timings.');
79
+ previousElapsed = f.elapsed;
80
+ if (f.input_text !== undefined) requireValue(text(f.input_text), 'The trace contains invalid input-token text.');
81
+ if (f.token_bytes !== undefined) {
82
+ requireValue(Array.isArray(f.token_bytes) && f.token_bytes.length <= LIMITS.tokenText &&
83
+ f.token_bytes.every(value => integer(value, 0, 255)), 'The trace contains invalid token bytes.');
84
+ }
85
+ requireValue(Array.isArray(f.layers) && f.layers.length === c.num_hidden_layers, 'The trace contains an incomplete frame.');
86
+ for (let i = 0; i < c.num_hidden_layers; i++) {
87
+ const l = f.layers[i];
88
+ const linear = c.layer_types[i] === 'linear_attention';
89
+ const heads = linear ? c.linear_num_value_heads : c.num_attention_heads;
90
+ const moe = Boolean(c.num_experts) && !(c.mlp_only_layers || []).includes(i) && i >= (c.first_k_dense_replace || 0);
91
+ requireValue(object(l), 'The trace contains an invalid layer.');
92
+ if (l.index !== undefined) requireValue(l.index === i, 'The trace layer order is inconsistent.');
93
+ vector(l.heads, heads, nonnegative, 'The trace contains invalid head measurements.');
94
+ requireValue(nonnegative(l.ffn) && nonnegative(l.residual), 'The trace contains invalid layer output measurements.');
95
+ if (moe) {
96
+ vector(l.experts, c.num_experts_per_tok, value => integer(value, 0, c.num_experts - 1), 'The trace contains invalid expert routing.');
97
+ requireValue(new Set(l.experts).size === c.num_experts_per_tok, 'The trace repeats a routed expert.');
98
+ vector(l.weights, c.num_experts_per_tok, probability, 'The trace contains invalid expert weights.');
99
+ requireValue(Math.abs(l.weights.reduce((sum, value) => sum + value, 0) - 1) <= 0.0001,
100
+ 'The trace expert weights are not normalized.');
101
+ requireValue(nonnegative(l.shared) && nonnegative(l.routed), 'The trace contains invalid expert output measurements.');
102
+ }
103
+ if (linear) {
104
+ vector(l.write_gate, heads, probability, 'The trace contains invalid write gates.');
105
+ vector(l.retention, heads, probability, 'The trace contains invalid retention gates.');
106
+ vector(l.state_rms, heads, nonnegative, 'The trace contains invalid recurrent state measurements.');
107
+ } else {
108
+ vector(l.attention, heads, object, 'The trace contains invalid attention measurements.');
109
+ for (const a of l.attention) {
110
+ requireValue(nonnegative(a.entropy), 'The trace contains invalid attention entropy.');
111
+ if (model.learned_sink || a.sink !== undefined) {
112
+ requireValue(probability(a.sink), 'The trace contains an invalid attention sink.');
113
+ }
114
+ requireValue(Array.isArray(a.top) && a.top.length <= 8 && a.top.length > 0 &&
115
+ a.top.every(pair => Array.isArray(pair) && pair.length === 2 && integer(pair[0], 0, f.input_position) && probability(pair[1])),
116
+ 'The trace contains invalid attention positions.');
117
+ requireValue(new Set(a.top.map(pair => pair[0])).size === a.top.length,
118
+ 'The trace repeats an attention position.');
119
+ requireValue(a.top.reduce((sum, pair) => sum + pair[1], 0) + (a.sink || 0) <= 1 + EPSILON,
120
+ 'The trace attention mass exceeds one.');
121
+ }
122
+ }
123
+ }
124
+ }
125
+ return model;
126
+ }
127
+ root.validateObservatoryTrace = validateObservatoryTrace;
128
+ if (typeof module !== 'undefined' && module.exports) module.exports = { validateObservatoryTrace, LIMITS };
129
+ })(typeof globalThis !== 'undefined' ? globalThis : this);
traces/flint-sky-q8.json.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2e1ea92da925516800b5001974a815eb3ea06c76b9542e9345b43ae7048fc524
3
+ size 10924016
traces/index.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "id": "flint-sky-q8",
4
+ "model": "flint",
5
+ "prompt": "Explain why the sky is blue in two sentences.",
6
+ "tokens": 59,
7
+ "file": "traces/flint-sky-q8.json.gz",
8
+ "sha256": "313c88cce6d4f6c46502c14a758f211e2943e1b54fbef150cab20e1de08d7fa9",
9
+ "gzip_sha256": "2e1ea92da925516800b5001974a815eb3ea06c76b9542e9345b43ae7048fc524",
10
+ "bytes": 27687499,
11
+ "compressed_bytes": 10924016,
12
+ "created": 1792715906116
13
+ },
14
+ {
15
+ "id": "qwen-sky-q8",
16
+ "model": "qwen",
17
+ "prompt": "Explain why the sky is blue in two sentences.",
18
+ "tokens": 44,
19
+ "file": "traces/qwen-sky-q8.json.gz",
20
+ "sha256": "69a80cde37242cede02aa7e04a7f1c27c12e9db1abb80c715b96475713f61f75",
21
+ "gzip_sha256": "2ebd0a811fdda05bd6091ae8daf71781f39554ae9404e7f41b2d9ab3d0667e66",
22
+ "bytes": 13083025,
23
+ "compressed_bytes": 5642915,
24
+ "created": 1792719501084
25
+ }
26
+ ]
traces/qwen-sky-q8.json.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2ebd0a811fdda05bd6091ae8daf71781f39554ae9404e7f41b2d9ab3d0667e66
3
+ size 5642915
verify.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Exercise the public viewer with real bundled captures, sequentially in one browser."""
2
+ import argparse,json,pathlib,tempfile
3
+ from playwright.sync_api import sync_playwright,expect
4
+
5
+ def main():
6
+ parser=argparse.ArgumentParser();parser.add_argument('--base',default='http://localhost:8000');parser.add_argument('--chromium');parser.add_argument('--out',default='reports');args=parser.parse_args()
7
+ out=pathlib.Path(args.out);out.mkdir(parents=True,exist_ok=True);checks=[];errors=[];failed_requests=[]
8
+ def passed(name):checks.append(name);print('PASS '+name,flush=True)
9
+ with sync_playwright() as p:
10
+ browser=p.chromium.launch(headless=True,**({'executable_path':args.chromium} if args.chromium else {}),args=['--disable-dev-shm-usage'])
11
+ try:
12
+ context=browser.new_context(viewport={'width':1440,'height':1100},permissions=['clipboard-read','clipboard-write'],accept_downloads=True)
13
+ page=context.new_page();page.on('pageerror',lambda e:errors.append(str(e)));page.on('response',lambda r:failed_requests.append({'url':r.url,'status':r.status}) if r.status>=400 else None)
14
+ page.goto(args.base);page.wait_for_function('typeof S!=="undefined"&&S.frames.length===59&&!S.loadingTrace',timeout=90000)
15
+ assert page.evaluate('S.model.id==="flint"&&S.frames[0].layers.length===49&&S.frame===0');expect(page.locator('#expertGrid button')).to_have_count(256);passed('Flint example: 59 measured frames and 49 blocks')
16
+ expected=page.evaluate('S.frames[S.frame].layers[S.layer].heads[S.head].toFixed(3)+" RMS"');expect(page.locator('#headValue')).to_have_text(expected);passed('Inspector displays actual selected-frame RMS')
17
+ page.locator('#openBlock').click();expect(page.locator('#detailDialog')).to_be_visible();expect(page.locator('#dBlockExperts button')).to_have_count(256);expect(page.locator('#dBlockRoutes button')).to_have_count(6);page.keyboard.press('Escape');passed('Fullscreen block exposes every expert and six actual routes')
18
+ page.locator('#expertList button').first.click();expect(page.locator('#dExpertStatus')).to_have_text('Selected');expect(page.locator('#dTimeline button')).to_have_count(59);page.locator('#detailClose').click();passed('Selected expert has a complete token timeline')
19
+ page.locator('#playSpeed').select_option('250');page.locator('#runButton').click();page.wait_for_function('S.frame>=2',timeout=10000);page.locator('#playButton').click();assert page.evaluate('S.timer===null');page.locator('#liveButton').click();assert page.evaluate('S.frame===58');page.locator('#stepBack').click();assert page.evaluate('S.frame===57');passed('Replay, speed, pause, step and jump to end change selected frames')
20
+ page.locator('#historyButton').click();page.wait_for_function('S.geometry.history===true');page.locator('#structureButton').click();page.wait_for_function('S.geometry.history===false');passed('Token-history heatmap and structure switch')
21
+ with tempfile.TemporaryDirectory() as temp:
22
+ export=pathlib.Path(temp)/'trace.json'
23
+ with page.expect_download() as d:page.locator('#exportButton').click()
24
+ d.value.save_as(export);trace=json.loads(export.read_text());assert len(trace['frames'])==59
25
+ page.locator('#importFile').set_input_files(str(export));page.wait_for_function('!S.loadingTrace&&S.trace.frames.length===59');assert page.evaluate('S.frame===58');passed('Export/import retains the complete measured trace')
26
+ trace['frames'][0]['layers'][12]['heads'][0]=-1;bad=pathlib.Path(temp)/'invalid.json';bad.write_text(json.dumps(trace))
27
+ page.locator('#importFile').set_input_files(str(bad));expect(page.locator('#toast')).to_contain_text('invalid head measurements');assert page.evaluate('S.frames[0].layers[12].heads[0]>=0&&S.frame===58');expect(page.locator('#runButton')).to_be_enabled();page.locator('#runButton').click();page.wait_for_function('S.frame>=1',timeout=10000);page.locator('#playButton').click();passed('Invalid import preserves the loaded capture and working replay')
28
+ page.locator('#scrubber').fill('12');page.locator('#modelSelect').select_option('qwen');page.wait_for_function('S.model.id==="qwen"&&S.frames.length===44&&!S.switching',timeout=90000)
29
+ expect(page.locator('#headGrid button')).to_have_count(48);assert page.evaluate('S.frames[0].layers.length===64');page.locator('#flowAttention').click();expect(page.locator('#dMemory')).to_be_visible();assert 'Write gate' in page.locator('#dMemory').inner_text();page.keyboard.press('Escape');passed('Qwen has 64 blocks and measured recurrent memory')
30
+ for _ in range(3):page.locator('#nextLayer').click()
31
+ expect(page.locator('#headGrid button')).to_have_count(24);page.locator('#flowAttention').click();expect(page.locator('#dAttentionRows')).to_be_visible();page.keyboard.press('Escape');page.locator('#flowMlp').click();expect(page.locator('#dFfnWidth')).to_have_text('17408');page.keyboard.press('Escape');passed('Qwen full-attention and dense feed-forward inspectors')
32
+ page.locator('#modelSelect').select_option('flint');page.wait_for_function('S.model.id==="flint"&&!S.switching');assert page.evaluate('S.frame===12');passed('Switching models preserves each selected trace and token')
33
+ page.locator('#modelCanvas').focus();old=page.evaluate('S.layer');page.keyboard.press('ArrowDown');assert page.evaluate('S.layer')==old+1;page.keyboard.press('Enter');expect(page.locator('#detailDialog')).to_be_visible();page.keyboard.press('Escape');passed('Keyboard topology navigation and fullscreen access')
34
+ page.locator('#shareButton').click();expect(page.locator('#toast')).to_contain_text('view link copied');url=page.evaluate('navigator.clipboard.readText()');assert 'model=flint' in url and 'token=13' in url;passed('Share link records model, layer and token')
35
+ page.locator('#toast').wait_for(state='hidden');page.screenshot(path=str(out/'desktop.png'),full_page=True)
36
+ for width in [390,320]:
37
+ page.set_viewport_size({'width':width,'height':844});assert page.evaluate('document.documentElement.scrollWidth<=innerWidth'),width
38
+ page.locator('#openBlock').click();assert page.locator('#detailDialog').bounding_box()['width']<=width+1;page.keyboard.press('Escape')
39
+ page.screenshot(path=str(out/'phone.png'),full_page=True);passed('320px and 390px layouts and fullscreen fit their viewport')
40
+ page.goto(args.base.rstrip('/')+'/?model=qwen&layer=3&token=7');page.wait_for_function('S.model?.id==="qwen"&&S.frames.length===44&&!S.loadingTrace&&S.frame===6',timeout=90000);assert page.evaluate('S.layer===3');passed('Shared deep link opens the requested example, layer and token')
41
+ page.locator('#aboutButton').click();expect(page.locator('#aboutContent')).to_contain_text('95th percentile');expect(page.locator('#aboutSource')).to_have_attribute('href','https://huggingface.co/Qwen/Qwen3.8-27B/blob/main/config.json');page.locator('#closeAbout').click();passed('Explanation and model configuration link follow model selection')
42
+ assert not errors,errors;assert not failed_requests,failed_requests;passed('No uncaught browser errors or failed release requests')
43
+ context.close()
44
+ # Failure injection uses a fresh context so a successful cache cannot hide it.
45
+ recovery=browser.new_context(viewport={'width':390,'height':844});page=recovery.new_page();blocked=[True]
46
+ def capture_route(route):
47
+ if blocked[0]:route.abort()
48
+ else:route.continue_()
49
+ page.route('**/traces/*.json.gz',capture_route);page.goto(args.base);expect(page.locator('#engineStatus')).to_have_text('Trace unavailable',timeout=30000);assert page.evaluate('S.config.num_hidden_layers===49');blocked[0]=False;page.locator('#runButton').click();page.wait_for_function('S.frames.length===59&&!S.loadingTrace',timeout=90000);expect(page.locator('#engineStatus')).to_contain_text('Measured Q8 replay');recovery.close();passed('Failed capture leaves topology visible and Retry recovers')
50
+ touch=browser.new_context(viewport={'width':390,'height':844},has_touch=True,is_mobile=True);page=touch.new_page();page.goto(args.base);page.wait_for_function('S.frames.length===59&&!S.loadingTrace',timeout=90000);page.locator('#openBlock').tap();expect(page.locator('#detailDialog')).to_be_visible();page.locator('#detailClose').tap();touch.close();passed('Touch interaction opens and closes fullscreen inspection')
51
+ finally:browser.close()
52
+ (out/'results.json').write_text(json.dumps({'passed':len(checks),'checks':checks,'browser_errors':errors,'failed_requests':failed_requests},indent=2)+'\n')
53
+ print(json.dumps({'passed':len(checks),'errors':errors,'failed_requests':failed_requests}))
54
+ if __name__=='__main__':main()