Yashp2003 commited on
Commit
7b7aad4
·
verified ·
1 Parent(s): 0073703

Update logbook: Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models

Browse files
README.md CHANGED
@@ -11,6 +11,7 @@ tags:
11
  - open-experiment
12
  - icml2026-repro
13
  - paper-rlVGCyjqnt
 
14
  ---
15
 
16
  # Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models
 
11
  - open-experiment
12
  - icml2026-repro
13
  - paper-rlVGCyjqnt
14
+ - arxiv:2603.00190
15
  ---
16
 
17
  # Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models
index.html CHANGED
@@ -21,6 +21,36 @@
21
  </div>
22
  </aside>
23
  <main id="content">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  <div id="page"></div>
25
  </main>
26
  </div>
 
21
  </div>
22
  </aside>
23
  <main id="content">
24
+ <nav id="view-tabs" aria-label="Logbook views">
25
+ <a data-view="code" href="#/view/code/index">
26
+ <svg viewBox="0 0 24 24" aria-hidden="true">
27
+ <path d="m18 16 4-4-4-4" />
28
+ <path d="m6 8-4 4 4 4" />
29
+ <path d="m14.5 4-5 16" />
30
+ </svg>
31
+ <span>Logbook</span>
32
+ </a>
33
+ <a data-view="trace" href="#/view/trace">
34
+ <svg viewBox="0 0 24 24" aria-hidden="true">
35
+ <path d="M8 5h13" />
36
+ <path d="M13 12h8" />
37
+ <path d="M13 19h8" />
38
+ <path d="M3 10a2 2 0 0 0 2 2h3" />
39
+ <path d="M3 5v12a2 2 0 0 0 2 2h3" />
40
+ </svg>
41
+ <span>Traces</span>
42
+ </a>
43
+ <a data-view="workspace" href="#/view/workspace">
44
+ <svg viewBox="0 0 24 24" aria-hidden="true">
45
+ <path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
46
+ </svg>
47
+ <span>Workspace</span>
48
+ </a>
49
+ </nav>
50
+ <header id="logbook-header">
51
+ <h1 id="logbook-title"></h1>
52
+ <div id="logbook-cli"></div>
53
+ </header>
54
  <div id="page"></div>
55
  </main>
56
  </div>
logbook.css CHANGED
@@ -1,6 +1,6 @@
1
  :root {
2
  --bg: #ffffff;
3
- --paper: #fdfcf9;
4
  --panel: #ffffff;
5
  --ink: #1f2937;
6
  --muted: #6b7280;
@@ -9,7 +9,7 @@
9
  --accent-strong: #ea580c;
10
  --accent-soft: #fff7ed;
11
  --accent-line: rgba(249, 115, 22, 0.16);
12
- --grid-line: rgba(31, 41, 55, 0.045);
13
  --code-bg: #f3f4f6;
14
  --radius: 12px;
15
  --serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Georgia, serif;
@@ -31,6 +31,7 @@ body {
31
 
32
  html {
33
  scroll-behavior: smooth;
 
34
  }
35
 
36
  body {
@@ -47,6 +48,11 @@ body {
47
  min-height: 100vh;
48
  }
49
 
 
 
 
 
 
50
  /* ---- sidebar (composition-book cover) ---- */
51
  #sidebar {
52
  width: 280px;
@@ -97,6 +103,15 @@ body {
97
  padding-top: 8px;
98
  }
99
 
 
 
 
 
 
 
 
 
 
100
  #tree a {
101
  display: block;
102
  padding: 6px 10px;
@@ -105,6 +120,9 @@ body {
105
  text-decoration: none;
106
  font-size: 14px;
107
  transition: background 0.12s, color 0.12s;
 
 
 
108
  }
109
 
110
  #tree a:hover {
@@ -143,7 +161,7 @@ body {
143
  #content {
144
  flex: 1;
145
  min-width: 0;
146
- padding: 48px 40px 120px;
147
  background-color: var(--paper);
148
  background-image:
149
  linear-gradient(var(--grid-line) 1px, transparent 1px),
@@ -152,10 +170,28 @@ body {
152
  background-position: center top;
153
  }
154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  #page {
156
  width: 100%;
157
  min-width: 0;
158
- max-width: 1052px;
159
  margin: 0 auto;
160
  }
161
 
@@ -170,10 +206,7 @@ body {
170
  }
171
 
172
  .page-layout {
173
- display: grid;
174
- grid-template-columns: minmax(0, 760px) 248px;
175
- gap: 44px;
176
- align-items: start;
177
  }
178
 
179
  .page-body {
@@ -188,18 +221,26 @@ body {
188
 
189
  /* ---- pinned notes ---- */
190
  .pinned-notes {
191
- margin: 30px 0 0;
192
  }
193
  .pinned-notes-list .cell {
194
  margin: 0;
195
- border-color: rgba(249, 115, 22, 0.55);
 
 
 
 
 
 
 
 
 
 
 
196
  }
197
  .pinned-notes-list .cell + .cell {
198
  margin-top: 12px;
199
  }
200
- .cell.pinned-source {
201
- border-color: rgba(249, 115, 22, 0.55);
202
- }
203
  .book-intro.has-pinned-notes {
204
  border-bottom: none;
205
  padding-bottom: 22px;
@@ -376,26 +417,25 @@ body {
376
  /* ---- notebook-style cells ---- */
377
  .cell {
378
  max-width: 100%;
379
- border: 1px solid var(--line);
380
- border-radius: 10px;
381
- background: rgba(255, 255, 255, 0.86);
382
- margin: 18px 0;
383
- overflow: hidden;
384
- box-shadow: 0 2px 10px rgba(31, 41, 55, 0.035);
385
  }
386
  .cell-head {
387
  display: flex;
388
  justify-content: space-between;
389
  gap: 16px;
390
- align-items: center;
391
- padding: 14px 18px;
392
- background: rgba(255, 255, 255, 0.92);
393
- border-bottom: 1px solid var(--line);
394
  }
395
  .cell-head.no-title {
396
  justify-content: flex-end;
397
- padding-top: 10px;
398
- padding-bottom: 10px;
399
  }
400
  .cell-title {
401
  flex: 1;
@@ -427,7 +467,7 @@ body {
427
  }
428
  .cell-body {
429
  min-width: 0;
430
- padding: 14px 18px 18px;
431
  }
432
  .cell.dashboard .cell-body {
433
  padding: 0;
@@ -447,9 +487,6 @@ body {
447
  #page .cell-body > :last-child {
448
  margin-bottom: 0;
449
  }
450
- .cell.code .cell-head {
451
- background: #fbfbfc;
452
- }
453
  .figure-fit {
454
  position: relative;
455
  overflow: hidden;
@@ -622,9 +659,40 @@ body {
622
  border: 1px solid var(--line);
623
  border-radius: 10px;
624
  overflow: hidden;
625
- margin: 12px 0;
626
  background: var(--panel);
627
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  .jp-gutter {
629
  flex: 0 0 46px;
630
  padding: 13px 0 0 13px;
@@ -652,6 +720,8 @@ body {
652
  border-radius: 0;
653
  background: none;
654
  padding: 12px 16px 12px 0;
 
 
655
  }
656
  .jp-in-body .code-accordion {
657
  margin: 0;
@@ -1055,11 +1125,13 @@ table.board tr.linked-row:hover a {
1055
  align-items: center;
1056
  flex-wrap: wrap;
1057
  gap: 8px;
1058
- margin: 4px 0 22px;
1059
  font-size: 12.5px;
1060
  color: var(--muted);
1061
  }
1062
- #page .agent-hint code {
 
 
1063
  background: var(--code-bg);
1064
  padding: 2px 9px;
1065
  border-radius: 6px;
@@ -1067,6 +1139,9 @@ table.board tr.linked-row:hover a {
1067
  font-size: 12px;
1068
  font-weight: 500;
1069
  color: var(--ink);
 
 
 
1070
  }
1071
  .agent-hint .copy {
1072
  flex: 0 0 auto;
@@ -1094,155 +1169,57 @@ table.board tr.linked-row:hover a {
1094
  font-size: 12px;
1095
  color: var(--muted);
1096
  }
1097
-
1098
- /* ---- logbook summary stats ---- */
1099
- .logbook-stats {
1100
  display: flex;
 
1101
  flex-wrap: wrap;
1102
- gap: 12px;
1103
- margin: 0 0 28px;
 
1104
  }
1105
- .stat-tile {
1106
- position: relative;
1107
  display: inline-flex;
1108
  align-items: center;
1109
- gap: 11px;
1110
- border: 1px solid var(--line);
1111
- background: var(--panel);
1112
- border-radius: var(--radius);
1113
- padding: 12px 23px;
1114
- font: inherit;
1115
- text-align: left;
1116
- cursor: pointer;
1117
- transition: border-color 0.12s, box-shadow 0.12s;
1118
- }
1119
- .stat-tile:hover:not([disabled]) {
1120
- border-color: rgba(249, 115, 22, 0.45);
1121
- box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06);
1122
- }
1123
- .stat-tile:focus-visible {
1124
- outline: 2px solid var(--accent);
1125
- outline-offset: 2px;
1126
- }
1127
- .stat-tile[disabled] {
1128
- cursor: default;
1129
- opacity: 0.7;
1130
- }
1131
- .stat-tile.open {
1132
- border-color: rgba(249, 115, 22, 0.6);
1133
- box-shadow: 0 3px 12px rgba(31, 41, 55, 0.08);
1134
- }
1135
- .stat-icon {
1136
- width: 24px;
1137
- height: 24px;
1138
- flex: 0 0 24px;
1139
- object-fit: contain;
1140
- align-self: center;
1141
- }
1142
- .stat-text {
1143
- display: flex;
1144
- align-items: baseline;
1145
- gap: 8px;
1146
- white-space: nowrap;
1147
- line-height: 1;
1148
- }
1149
- .stat-num {
1150
- font-family: var(--mono);
1151
- font-size: 20px;
1152
- font-weight: 600;
1153
- line-height: 1;
1154
  color: var(--accent-strong);
1155
- }
1156
- .stat-label {
1157
- font-size: 15px;
1158
- line-height: 1;
1159
- color: var(--muted);
1160
- }
1161
- .stat-caret {
1162
- margin-left: 2px;
1163
- font-size: 10px;
1164
- color: var(--muted);
1165
- align-self: center;
1166
- transition: transform 0.12s;
1167
- }
1168
- .stat-tile.open .stat-caret {
1169
- transform: rotate(180deg);
1170
- }
1171
- .stat-popover {
1172
- position: absolute;
1173
- top: 100%;
1174
- left: 0;
1175
- margin-top: 6px;
1176
- min-width: 300px;
1177
- max-width: min(460px, 92vw);
1178
- max-height: 340px;
1179
- overflow-y: auto;
1180
- z-index: 20;
1181
- background: var(--panel);
1182
- border: 1px solid var(--line);
1183
- border-radius: var(--radius);
1184
- box-shadow: 0 8px 28px rgba(31, 41, 55, 0.12);
1185
- padding: 6px;
1186
- }
1187
- .stat-popover[hidden] {
1188
- display: none;
1189
- }
1190
- .stat-pop-head {
1191
- padding: 6px 10px 8px;
1192
- font-size: 11.5px;
1193
- font-weight: 700;
1194
- letter-spacing: 0.03em;
1195
- text-transform: uppercase;
1196
- color: var(--muted);
1197
- }
1198
- .stat-row {
1199
- display: flex;
1200
- align-items: flex-start;
1201
- gap: 10px;
1202
- padding: 9px 11px;
1203
- border-radius: 9px;
1204
- border: 1px solid transparent;
1205
  text-decoration: none;
1206
- color: inherit;
1207
- cursor: pointer;
1208
  }
1209
- .stat-row:hover {
1210
- border-color: rgba(249, 115, 22, 0.4);
1211
- background: var(--accent-soft);
 
1212
  }
1213
- .stat-row-ico {
1214
- font-size: 15px;
1215
- line-height: 1.3;
1216
  flex: 0 0 auto;
 
 
 
 
 
1217
  }
1218
- .stat-row-main {
1219
- min-width: 0;
1220
- flex: 1;
1221
- }
1222
- .stat-row-title {
1223
- font-family: var(--mono);
1224
- font-size: 12.5px;
1225
- font-weight: 600;
1226
- color: var(--ink);
1227
- overflow: hidden;
1228
- text-overflow: ellipsis;
1229
- white-space: nowrap;
1230
- }
1231
- .stat-row-meta {
1232
- margin-top: 2px;
1233
- font-size: 12px;
1234
- color: var(--muted);
1235
- }
1236
- .stat-row-state.open {
1237
- color: var(--accent);
1238
- font-weight: 600;
1239
- border-radius: 5px;
1240
- padding: 1px 5px;
1241
- margin: -1px -2px;
1242
  }
1243
- .stat-row-state.open:hover {
1244
- background: rgba(249, 115, 22, 0.14);
1245
- text-decoration: underline;
1246
  }
1247
  .art-ico {
1248
  width: 1em;
@@ -1250,6 +1227,20 @@ table.board tr.linked-row:hover a {
1250
  object-fit: contain;
1251
  vertical-align: -0.15em;
1252
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1253
 
1254
  /* ---- scroll-to-resource highlight ---- */
1255
  .res-flash {
@@ -1294,108 +1285,11 @@ table.board tr.linked-row:hover a {
1294
  font-size: 1.05em;
1295
  line-height: 1;
1296
  }
1297
- #page .res-chip:hover,
1298
- #page .res-chip.res-hl {
1299
- border-color: var(--accent);
1300
- background: var(--accent-soft);
1301
- color: var(--accent-strong);
1302
- }
1303
- #page a.res-link.res-hl {
1304
- background: var(--accent-soft);
1305
- border-radius: 4px;
1306
- }
1307
- .rail-item.res-hl {
1308
- border-color: var(--accent);
1309
- background: var(--accent-soft);
1310
- box-shadow: 0 3px 12px rgba(249, 115, 22, 0.14);
1311
- }
1312
- .rail-item.res-hl .rail-title {
1313
- color: var(--accent-strong);
1314
- }
1315
- .rail-item.rail-local {
1316
- cursor: default;
1317
- }
1318
- .artifact-chip.res-hl {
1319
  border-color: var(--accent);
1320
  background: var(--accent-soft);
1321
- }
1322
-
1323
- /* ---- contextual resources rail ---- */
1324
- .context-rail {
1325
- position: relative;
1326
- width: 248px;
1327
- }
1328
- .context-rail[hidden] {
1329
- display: none;
1330
- }
1331
- .rail-kind {
1332
- display: flex;
1333
- align-items: center;
1334
- gap: 5px;
1335
- font-family: var(--mono);
1336
- font-size: 10px;
1337
- text-transform: uppercase;
1338
- letter-spacing: 0.08em;
1339
- font-weight: 600;
1340
- color: var(--accent);
1341
- margin-bottom: 4px;
1342
- }
1343
- .rail-item {
1344
- position: absolute;
1345
- left: 0;
1346
- right: 0;
1347
- display: block;
1348
- border: 1px solid var(--line);
1349
- border-radius: 10px;
1350
- background: var(--panel);
1351
- padding: 9px 12px;
1352
- margin-bottom: 8px;
1353
- text-decoration: none;
1354
- color: inherit;
1355
- transition: border-color 0.14s, box-shadow 0.14s;
1356
- }
1357
- .rail-item:hover {
1358
- border-color: rgba(249, 115, 22, 0.45);
1359
- box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06);
1360
- }
1361
- .rail-title {
1362
- font-family: var(--mono);
1363
- font-size: 12.5px;
1364
- font-weight: 600;
1365
- color: var(--ink);
1366
- overflow-wrap: anywhere;
1367
- line-height: 1.4;
1368
- }
1369
- .rail-item:hover .rail-title {
1370
  color: var(--accent-strong);
1371
  }
1372
- .rail-meta {
1373
- font-size: 11.5px;
1374
- color: var(--muted);
1375
- margin-top: 2px;
1376
- }
1377
-
1378
- @media (max-width: 1400px) {
1379
- .page-layout {
1380
- display: block;
1381
- }
1382
- .context-rail {
1383
- width: 100%;
1384
- margin-top: 28px;
1385
- position: static;
1386
- min-height: 0 !important;
1387
- display: grid;
1388
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1389
- gap: 10px;
1390
- }
1391
- .context-rail[hidden] {
1392
- display: none;
1393
- }
1394
- .context-rail .rail-item {
1395
- position: static;
1396
- margin-bottom: 0;
1397
- }
1398
- }
1399
 
1400
  /* ---- connect footer + modal ---- */
1401
  #sidebar-foot {
@@ -1571,27 +1465,665 @@ table.board tr.linked-row:hover a {
1571
  color: #52d08a;
1572
  }
1573
 
1574
- @media (max-width: 720px) {
1575
- #app {
1576
- flex-direction: column;
1577
- }
1578
- #sidebar {
1579
- width: 100%;
1580
- flex: none;
1581
- height: auto;
1582
- position: static;
1583
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1584
  #content {
1585
  display: block;
1586
  width: 100%;
1587
  padding: 28px 20px 80px;
1588
  overflow-x: hidden;
1589
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1590
  #page {
1591
  width: 100%;
1592
  max-width: 100%;
1593
  }
1594
- #page h1 {
 
1595
  font-size: 30px;
1596
  }
1597
  .cell-head {
 
1
  :root {
2
  --bg: #ffffff;
3
+ --paper: #ffffff;
4
  --panel: #ffffff;
5
  --ink: #1f2937;
6
  --muted: #6b7280;
 
9
  --accent-strong: #ea580c;
10
  --accent-soft: #fff7ed;
11
  --accent-line: rgba(249, 115, 22, 0.16);
12
+ --grid-line: rgba(31, 41, 55, 0.02);
13
  --code-bg: #f3f4f6;
14
  --radius: 12px;
15
  --serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Georgia, serif;
 
31
 
32
  html {
33
  scroll-behavior: smooth;
34
+ scrollbar-gutter: stable;
35
  }
36
 
37
  body {
 
48
  min-height: 100vh;
49
  }
50
 
51
+ body[data-view="trace"] #sidebar-foot,
52
+ body[data-view="workspace"] #sidebar-foot {
53
+ display: none;
54
+ }
55
+
56
  /* ---- sidebar (composition-book cover) ---- */
57
  #sidebar {
58
  width: 280px;
 
103
  padding-top: 8px;
104
  }
105
 
106
+ #tree .tree-label {
107
+ padding: 6px 10px 8px;
108
+ color: #777a83;
109
+ font-size: 10px;
110
+ font-weight: 700;
111
+ letter-spacing: 0.12em;
112
+ text-transform: uppercase;
113
+ }
114
+
115
  #tree a {
116
  display: block;
117
  padding: 6px 10px;
 
120
  text-decoration: none;
121
  font-size: 14px;
122
  transition: background 0.12s, color 0.12s;
123
+ overflow: hidden;
124
+ text-overflow: ellipsis;
125
+ white-space: nowrap;
126
  }
127
 
128
  #tree a:hover {
 
161
  #content {
162
  flex: 1;
163
  min-width: 0;
164
+ padding: 24px 40px 120px;
165
  background-color: var(--paper);
166
  background-image:
167
  linear-gradient(var(--grid-line) 1px, transparent 1px),
 
170
  background-position: center top;
171
  }
172
 
173
+ #logbook-header {
174
+ width: 100%;
175
+ max-width: 1080px;
176
+ margin: 0 auto 20px;
177
+ }
178
+ #logbook-title {
179
+ font-family: var(--serif);
180
+ font-size: 34px;
181
+ line-height: 1.15;
182
+ letter-spacing: -0.02em;
183
+ margin: 0 0 10px;
184
+ overflow-wrap: anywhere;
185
+ }
186
+ #logbook-cli {
187
+ display: grid;
188
+ gap: 7px;
189
+ }
190
+
191
  #page {
192
  width: 100%;
193
  min-width: 0;
194
+ max-width: 1080px;
195
  margin: 0 auto;
196
  }
197
 
 
206
  }
207
 
208
  .page-layout {
209
+ display: block;
 
 
 
210
  }
211
 
212
  .page-body {
 
221
 
222
  /* ---- pinned notes ---- */
223
  .pinned-notes {
224
+ margin: 30px 0 32px;
225
  }
226
  .pinned-notes-list .cell {
227
  margin: 0;
228
+ }
229
+ .pinned-notes-list .cell-title {
230
+ display: flex;
231
+ align-items: center;
232
+ gap: 7px;
233
+ }
234
+ .pin-ico {
235
+ flex: 0 0 auto;
236
+ width: 14px;
237
+ height: 14px;
238
+ fill: var(--accent);
239
+ stroke: none;
240
  }
241
  .pinned-notes-list .cell + .cell {
242
  margin-top: 12px;
243
  }
 
 
 
244
  .book-intro.has-pinned-notes {
245
  border-bottom: none;
246
  padding-bottom: 22px;
 
417
  /* ---- notebook-style cells ---- */
418
  .cell {
419
  max-width: 100%;
420
+ margin: 0 0 32px;
421
+ background: none;
422
+ border: none;
423
+ border-radius: 0;
424
+ box-shadow: none;
425
+ overflow: visible;
426
  }
427
  .cell-head {
428
  display: flex;
429
  justify-content: space-between;
430
  gap: 16px;
431
+ align-items: baseline;
432
+ padding: 0 0 5px;
433
+ background: none;
434
+ border-bottom: none;
435
  }
436
  .cell-head.no-title {
437
  justify-content: flex-end;
438
+ padding: 0 0 3px;
 
439
  }
440
  .cell-title {
441
  flex: 1;
 
467
  }
468
  .cell-body {
469
  min-width: 0;
470
+ padding: 0;
471
  }
472
  .cell.dashboard .cell-body {
473
  padding: 0;
 
487
  #page .cell-body > :last-child {
488
  margin-bottom: 0;
489
  }
 
 
 
490
  .figure-fit {
491
  position: relative;
492
  overflow: hidden;
 
659
  border: 1px solid var(--line);
660
  border-radius: 10px;
661
  overflow: hidden;
662
+ margin: 0;
663
  background: var(--panel);
664
  }
665
+ .jp-cmd {
666
+ display: flex;
667
+ align-items: baseline;
668
+ gap: 9px;
669
+ position: relative;
670
+ padding: 10px 16px 10px 0;
671
+ font-family: var(--mono);
672
+ font-size: 12px;
673
+ color: #8b8e98;
674
+ }
675
+ .jp-cmd-prompt {
676
+ color: var(--accent);
677
+ font-weight: 700;
678
+ }
679
+ #page .jp-cmd code {
680
+ min-width: 0;
681
+ color: #b6b9c2;
682
+ font-family: var(--mono);
683
+ font-size: 12px;
684
+ background: none;
685
+ padding: 0;
686
+ border-radius: 0;
687
+ overflow-wrap: anywhere;
688
+ }
689
+ .jp-cmd:hover .copy-snippet {
690
+ opacity: 1;
691
+ }
692
+ .jp-in-body .jp-cmd + .code-accordion,
693
+ .jp-in-body .jp-cmd + .snippet {
694
+ border-top: 1px solid rgba(255, 255, 255, 0.09);
695
+ }
696
  .jp-gutter {
697
  flex: 0 0 46px;
698
  padding: 13px 0 0 13px;
 
720
  border-radius: 0;
721
  background: none;
722
  padding: 12px 16px 12px 0;
723
+ overflow-y: auto;
724
+ max-height: 26em;
725
  }
726
  .jp-in-body .code-accordion {
727
  margin: 0;
 
1125
  align-items: center;
1126
  flex-wrap: wrap;
1127
  gap: 8px;
1128
+ margin: 0;
1129
  font-size: 12.5px;
1130
  color: var(--muted);
1131
  }
1132
+ .agent-hint code {
1133
+ flex: 1 1 18rem;
1134
+ min-width: 0;
1135
  background: var(--code-bg);
1136
  padding: 2px 9px;
1137
  border-radius: 6px;
 
1139
  font-size: 12px;
1140
  font-weight: 500;
1141
  color: var(--ink);
1142
+ overflow: hidden;
1143
+ text-overflow: ellipsis;
1144
+ white-space: nowrap;
1145
  }
1146
  .agent-hint .copy {
1147
  flex: 0 0 auto;
 
1169
  font-size: 12px;
1170
  color: var(--muted);
1171
  }
1172
+ .hub-destination {
 
 
1173
  display: flex;
1174
+ align-items: center;
1175
  flex-wrap: wrap;
1176
+ gap: 8px;
1177
+ color: var(--muted);
1178
+ font-size: 12.5px;
1179
  }
1180
+ .hub-destination a {
 
1181
  display: inline-flex;
1182
  align-items: center;
1183
+ gap: 6px;
1184
+ max-width: 100%;
1185
+ padding: 3px 9px;
1186
+ border: 1px solid var(--accent-line);
1187
+ border-radius: 999px;
1188
+ background: var(--accent-soft);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1189
  color: var(--accent-strong);
1190
+ font-family: var(--mono);
1191
+ font-size: 12px;
1192
+ font-weight: 650;
1193
+ line-height: 1.5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1194
  text-decoration: none;
1195
+ overflow-wrap: anywhere;
1196
+ transition: border-color 0.12s, background 0.12s, color 0.12s;
1197
  }
1198
+ .hub-destination a:hover {
1199
+ border-color: var(--accent);
1200
+ background: #ffedd5;
1201
+ color: #c2410c;
1202
  }
1203
+ .hub-destination svg {
1204
+ width: 13px;
1205
+ height: 13px;
1206
  flex: 0 0 auto;
1207
+ fill: none;
1208
+ stroke: currentColor;
1209
+ stroke-width: 1.8;
1210
+ stroke-linecap: round;
1211
+ stroke-linejoin: round;
1212
  }
1213
+
1214
+ .index-paper-link {
1215
+ margin: 14px 0 30px;
1216
+ font-size: 19px;
1217
+ line-height: 1.35;
1218
+ font-weight: 700;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1219
  }
1220
+ .index-paper-link a {
1221
+ text-underline-offset: 4px;
1222
+ text-decoration-thickness: 2px;
1223
  }
1224
  .art-ico {
1225
  width: 1em;
 
1227
  object-fit: contain;
1228
  vertical-align: -0.15em;
1229
  }
1230
+ .art-file-ico {
1231
+ width: 15px;
1232
+ height: 15px;
1233
+ flex: 0 0 auto;
1234
+ fill: none;
1235
+ stroke: currentColor;
1236
+ stroke-width: 1.7;
1237
+ stroke-linecap: round;
1238
+ stroke-linejoin: round;
1239
+ vertical-align: -0.2em;
1240
+ }
1241
+ .out-artifact-ico .art-file-ico {
1242
+ color: var(--muted);
1243
+ }
1244
 
1245
  /* ---- scroll-to-resource highlight ---- */
1246
  .res-flash {
 
1285
  font-size: 1.05em;
1286
  line-height: 1;
1287
  }
1288
+ #page .res-chip:hover {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1289
  border-color: var(--accent);
1290
  background: var(--accent-soft);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1291
  color: var(--accent-strong);
1292
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1293
 
1294
  /* ---- connect footer + modal ---- */
1295
  #sidebar-foot {
 
1465
  color: #52d08a;
1466
  }
1467
 
1468
+ /* ---- top-level logbook views ---- */
1469
+ #view-tabs {
1470
+ position: sticky;
1471
+ top: 0;
1472
+ z-index: 30;
1473
+ width: 100%;
1474
+ max-width: 1080px;
1475
+ margin: 0 auto 24px;
1476
+ padding-top: 10px;
1477
+ display: flex;
1478
+ align-items: center;
1479
+ justify-content: flex-start;
1480
+ gap: 26px;
1481
+ border-bottom: 1px solid var(--line);
1482
+ background: var(--paper);
1483
+ }
1484
+ #view-tabs a {
1485
+ display: inline-flex;
1486
+ align-items: center;
1487
+ gap: 8px;
1488
+ min-height: 44px;
1489
+ margin-bottom: -1px;
1490
+ color: var(--muted);
1491
+ border-bottom: 2px solid transparent;
1492
+ text-decoration: none;
1493
+ font-size: 13.5px;
1494
+ font-weight: 600;
1495
+ transition: color 0.12s, border-color 0.12s;
1496
+ }
1497
+ #view-tabs a:hover {
1498
+ color: var(--ink);
1499
+ }
1500
+ #view-tabs a.active {
1501
+ color: var(--accent-strong);
1502
+ border-bottom-color: var(--accent);
1503
+ }
1504
+ #view-tabs svg {
1505
+ width: 18px;
1506
+ height: 18px;
1507
+ flex: 0 0 auto;
1508
+ fill: none;
1509
+ stroke: currentColor;
1510
+ stroke-width: 2;
1511
+ stroke-linecap: round;
1512
+ stroke-linejoin: round;
1513
+ }
1514
+ .workspace-file svg,
1515
+ .workspace-folder summary svg,
1516
+ .workspace-download svg {
1517
+ width: 17px;
1518
+ height: 17px;
1519
+ flex: 0 0 auto;
1520
+ fill: none;
1521
+ stroke: currentColor;
1522
+ stroke-width: 1.7;
1523
+ stroke-linecap: round;
1524
+ stroke-linejoin: round;
1525
+ }
1526
+
1527
+ #page.trace-page,
1528
+ #page.workspace-page {
1529
+ max-width: 1080px;
1530
+ }
1531
+ .view-loading {
1532
+ padding: 72px 0;
1533
+ color: var(--muted);
1534
+ text-align: center;
1535
+ }
1536
+ .view-empty {
1537
+ margin: 48px 0;
1538
+ padding: 44px 28px;
1539
+ border: 1px dashed #d8dbe1;
1540
+ border-radius: var(--radius);
1541
+ background: rgba(255, 255, 255, 0.72);
1542
+ text-align: center;
1543
+ }
1544
+ .view-empty h2 {
1545
+ margin: 0 0 7px;
1546
+ font-size: 18px;
1547
+ }
1548
+ .view-empty p {
1549
+ max-width: 560px;
1550
+ margin: 0 auto;
1551
+ color: var(--muted);
1552
+ }
1553
+ .view-empty code {
1554
+ display: inline-block;
1555
+ margin-top: 18px;
1556
+ padding: 7px 10px;
1557
+ border-radius: 7px;
1558
+ background: var(--code-bg);
1559
+ font-family: var(--mono);
1560
+ font-size: 12px;
1561
+ }
1562
+ #page .repo-ref-link {
1563
+ display: inline-block;
1564
+ margin-top: 18px;
1565
+ padding: 8px 14px;
1566
+ border-radius: 8px;
1567
+ background: var(--accent-strong, #2158d0);
1568
+ color: #fff;
1569
+ font-weight: 600;
1570
+ text-decoration: none;
1571
+ }
1572
+ #page .repo-ref-link:hover,
1573
+ #page .repo-ref-link:focus-visible {
1574
+ color: #fff;
1575
+ filter: brightness(0.95);
1576
+ }
1577
+ .view-eyebrow {
1578
+ margin-bottom: 4px;
1579
+ color: var(--accent-strong);
1580
+ font-family: var(--mono);
1581
+ font-size: 11px;
1582
+ font-weight: 700;
1583
+ letter-spacing: 0.12em;
1584
+ text-transform: uppercase;
1585
+ }
1586
+
1587
+ /* ---- trace ---- */
1588
+ .trace-session {
1589
+ scroll-margin-top: 24px;
1590
+ }
1591
+ .trace-session + .trace-session {
1592
+ margin-top: 44px;
1593
+ padding-top: 40px;
1594
+ border-top: 1px solid var(--line);
1595
+ }
1596
+ .trace-session-title {
1597
+ margin: 0 0 14px;
1598
+ color: var(--ink);
1599
+ font-family: var(--serif);
1600
+ font-size: 22px;
1601
+ line-height: 1.2;
1602
+ letter-spacing: -0.02em;
1603
+ overflow-wrap: anywhere;
1604
+ }
1605
+ .workspace-header h1 {
1606
+ margin: 0;
1607
+ color: var(--ink);
1608
+ font-size: 30px;
1609
+ line-height: 1.2;
1610
+ letter-spacing: -0.025em;
1611
+ }
1612
+ .trace-meta {
1613
+ display: flex;
1614
+ flex-wrap: wrap;
1615
+ gap: 9px 20px;
1616
+ margin-bottom: 34px;
1617
+ padding: 14px 16px;
1618
+ border: 1px solid var(--line);
1619
+ border-radius: 10px;
1620
+ background: rgba(255, 255, 255, 0.78);
1621
+ color: var(--muted);
1622
+ font-family: var(--mono);
1623
+ font-size: 11px;
1624
+ }
1625
+ .trace-meta strong {
1626
+ color: var(--ink);
1627
+ font-weight: 650;
1628
+ }
1629
+ .trace-source-missing {
1630
+ color: #b45309;
1631
+ }
1632
+ .trace-timeline {
1633
+ position: relative;
1634
+ }
1635
+ .trace-timeline::before {
1636
+ content: "";
1637
+ position: absolute;
1638
+ top: 0;
1639
+ bottom: 0;
1640
+ left: 82px;
1641
+ width: 1px;
1642
+ background: #dedfe3;
1643
+ }
1644
+ .trace-load-controls {
1645
+ display: flex;
1646
+ align-items: center;
1647
+ justify-content: space-between;
1648
+ gap: 16px;
1649
+ margin: 22px 0 0 100px;
1650
+ padding-top: 16px;
1651
+ border-top: 1px solid var(--line);
1652
+ }
1653
+ .trace-load-progress {
1654
+ color: var(--muted);
1655
+ font-family: var(--mono);
1656
+ font-size: 11px;
1657
+ }
1658
+ .trace-load-more {
1659
+ padding: 7px 12px;
1660
+ border: 1px solid var(--line-strong);
1661
+ border-radius: 7px;
1662
+ background: var(--paper);
1663
+ color: var(--ink);
1664
+ cursor: pointer;
1665
+ font: 650 12px/1.2 var(--sans);
1666
+ }
1667
+ .trace-load-more:hover:not(:disabled) {
1668
+ border-color: var(--accent);
1669
+ color: var(--accent-strong);
1670
+ }
1671
+ .trace-load-more:disabled {
1672
+ cursor: default;
1673
+ opacity: 0.65;
1674
+ }
1675
+ .trace-entry {
1676
+ --trace-depth: 0;
1677
+ position: relative;
1678
+ display: grid;
1679
+ grid-template-columns: 100px minmax(0, 1fr);
1680
+ margin: 0 0 18px calc(var(--trace-depth) * 24px);
1681
+ }
1682
+ .trace-rail {
1683
+ position: relative;
1684
+ min-height: 36px;
1685
+ padding: 4px 28px 0 0;
1686
+ color: #8a8d95;
1687
+ text-align: right;
1688
+ font-family: var(--mono);
1689
+ }
1690
+ .trace-number,
1691
+ .trace-elapsed {
1692
+ display: block;
1693
+ white-space: nowrap;
1694
+ }
1695
+ .trace-number {
1696
+ font-size: 12px;
1697
+ font-weight: 650;
1698
+ }
1699
+ .trace-elapsed {
1700
+ margin-top: 3px;
1701
+ font-size: 10px;
1702
+ }
1703
+ .trace-dot {
1704
+ position: absolute;
1705
+ top: 10px;
1706
+ right: 11px;
1707
+ width: 11px;
1708
+ height: 11px;
1709
+ border: 2px solid var(--paper);
1710
+ border-radius: 50%;
1711
+ background: var(--accent);
1712
+ box-shadow: 0 0 0 1px #d7d9de;
1713
+ }
1714
+ .trace-card {
1715
+ min-width: 0;
1716
+ overflow: hidden;
1717
+ border: 1px solid #dddfe4;
1718
+ border-radius: 11px;
1719
+ background: rgba(255, 255, 255, 0.92);
1720
+ }
1721
+ .trace-card > header {
1722
+ display: flex;
1723
+ align-items: center;
1724
+ gap: 10px;
1725
+ min-height: 37px;
1726
+ padding: 8px 13px;
1727
+ border-bottom: 1px solid #eceef1;
1728
+ }
1729
+ .trace-status .trace-card > header {
1730
+ border-bottom: 0;
1731
+ padding-bottom: 5px;
1732
+ }
1733
+ .trace-kind {
1734
+ font-family: var(--mono);
1735
+ font-size: 10.5px;
1736
+ font-weight: 750;
1737
+ letter-spacing: 0.08em;
1738
+ text-transform: uppercase;
1739
+ }
1740
+ .trace-turn {
1741
+ color: var(--muted);
1742
+ font: 10px var(--mono);
1743
+ }
1744
+ .trace-status-badge {
1745
+ margin-left: auto;
1746
+ padding: 1px 6px;
1747
+ border-radius: 999px;
1748
+ background: #eef0f3;
1749
+ color: var(--muted);
1750
+ font: 9.5px var(--mono);
1751
+ text-transform: uppercase;
1752
+ }
1753
+ .trace-status-badge-error,
1754
+ .trace-status-badge-failed {
1755
+ background: #fef2f2;
1756
+ color: #b91c1c;
1757
+ }
1758
+ .trace-body {
1759
+ margin: 0;
1760
+ padding: 15px 17px 17px;
1761
+ overflow-wrap: anywhere;
1762
+ white-space: pre-wrap;
1763
+ font-family: var(--sans);
1764
+ font-size: 13px;
1765
+ line-height: 1.65;
1766
+ }
1767
+ .trace-reasoning .trace-card {
1768
+ border-style: dashed;
1769
+ border-color: #d7b98a;
1770
+ background: #fffdf8;
1771
+ }
1772
+ .trace-reasoning .trace-kind {
1773
+ color: #9a6b22;
1774
+ }
1775
+ .trace-reasoning .trace-body {
1776
+ font-style: italic;
1777
+ }
1778
+ .trace-user .trace-card {
1779
+ border-left: 3px solid #f3a66d;
1780
+ }
1781
+ .trace-tool_call .trace-card,
1782
+ .trace-tool_result .trace-card {
1783
+ border-color: #2d3036;
1784
+ background: #191a1e;
1785
+ color: #ececf0;
1786
+ }
1787
+ .trace-tool_call .trace-card > header,
1788
+ .trace-tool_result .trace-card > header {
1789
+ border-bottom-color: rgba(255, 255, 255, 0.1);
1790
+ }
1791
+ .trace-tool_call .trace-kind,
1792
+ .trace-tool_result .trace-kind {
1793
+ color: #f5a66d;
1794
+ }
1795
+ .trace-tool_call .trace-turn,
1796
+ .trace-tool_result .trace-turn {
1797
+ color: #979aa3;
1798
+ }
1799
+ .trace-tool_call .trace-body,
1800
+ .trace-tool_result .trace-body,
1801
+ .trace-output pre {
1802
+ font-family: var(--mono);
1803
+ font-size: 11.5px;
1804
+ line-height: 1.6;
1805
+ }
1806
+ #page .trace-tool_call pre.trace-body,
1807
+ #page .trace-tool_result pre.trace-body {
1808
+ margin: 0;
1809
+ padding: 15px 17px 17px;
1810
+ border: 0;
1811
+ border-radius: 0;
1812
+ background: transparent;
1813
+ color: #ececf0;
1814
+ }
1815
+ .trace-output {
1816
+ border-top: 1px dashed rgba(255, 255, 255, 0.14);
1817
+ }
1818
+ .trace-output summary {
1819
+ padding: 9px 14px;
1820
+ color: #aaaeb7;
1821
+ cursor: pointer;
1822
+ font: 700 10px var(--mono);
1823
+ letter-spacing: 0.06em;
1824
+ text-transform: uppercase;
1825
+ }
1826
+ #page .trace-output pre {
1827
+ max-height: 480px;
1828
+ margin: 0;
1829
+ padding: 0 16px 16px;
1830
+ border: 0;
1831
+ border-radius: 0;
1832
+ background: transparent;
1833
+ overflow: auto;
1834
+ color: #d7d8dd;
1835
+ white-space: pre-wrap;
1836
+ }
1837
+
1838
+ /* ---- workspace ---- */
1839
+ .workspace-header {
1840
+ padding-bottom: 24px;
1841
+ }
1842
+ .workspace-header p {
1843
+ margin: 0;
1844
+ color: var(--muted);
1845
+ font-family: var(--mono);
1846
+ font-size: 11px;
1847
+ }
1848
+ .workspace-inventory {
1849
+ overflow: hidden;
1850
+ border: 1px solid var(--line);
1851
+ border-radius: 11px;
1852
+ background: rgba(255, 255, 255, 0.92);
1853
+ }
1854
+ .workspace-folder > summary {
1855
+ display: flex;
1856
+ align-items: center;
1857
+ gap: 8px;
1858
+ min-height: 39px;
1859
+ padding: 8px 13px;
1860
+ background: #fafafa;
1861
+ cursor: pointer;
1862
+ font-weight: 650;
1863
+ list-style: none;
1864
+ }
1865
+ .workspace-folder > summary::-webkit-details-marker {
1866
+ display: none;
1867
+ }
1868
+ .workspace-folder > summary::after {
1869
+ content: "›";
1870
+ margin-left: auto;
1871
+ color: #989ba2;
1872
+ transform: rotate(90deg);
1873
+ }
1874
+ .workspace-folder:not([open]) > summary::after {
1875
+ transform: rotate(0);
1876
+ }
1877
+ .workspace-folder-children {
1878
+ padding-left: 20px;
1879
+ }
1880
+ .workspace-file {
1881
+ display: grid;
1882
+ grid-template-columns: minmax(180px, 1fr) 72px 78px 180px 36px;
1883
+ align-items: center;
1884
+ min-height: 44px;
1885
+ padding: 7px 10px 7px 13px;
1886
+ color: var(--muted);
1887
+ font-family: var(--mono);
1888
+ font-size: 10.5px;
1889
+ }
1890
+ .workspace-file-name {
1891
+ display: flex;
1892
+ align-items: center;
1893
+ min-width: 0;
1894
+ gap: 8px;
1895
+ color: var(--ink);
1896
+ font-family: var(--sans);
1897
+ font-size: 12.5px;
1898
+ font-weight: 550;
1899
+ }
1900
+ .workspace-file-name span {
1901
+ overflow: hidden;
1902
+ text-overflow: ellipsis;
1903
+ white-space: nowrap;
1904
+ }
1905
+ .workspace-file-type {
1906
+ width: fit-content;
1907
+ padding: 1px 6px;
1908
+ border-radius: 999px;
1909
+ background: var(--accent-soft);
1910
+ color: var(--accent-strong);
1911
+ text-transform: uppercase;
1912
+ }
1913
+ .workspace-download {
1914
+ display: inline-flex;
1915
+ align-items: center;
1916
+ justify-content: center;
1917
+ width: 30px;
1918
+ height: 30px;
1919
+ border-radius: 7px;
1920
+ color: var(--muted);
1921
+ }
1922
+ .workspace-download:hover {
1923
+ background: var(--accent-soft);
1924
+ color: var(--accent-strong);
1925
+ }
1926
+ .workspace-unpublished {
1927
+ color: #9ca3af;
1928
+ text-align: center;
1929
+ }
1930
+
1931
+ .workspace-header {
1932
+ display: flex;
1933
+ align-items: center;
1934
+ justify-content: space-between;
1935
+ gap: 16px;
1936
+ flex-wrap: wrap;
1937
+ }
1938
+ .workspace-toggle {
1939
+ display: inline-flex;
1940
+ align-items: center;
1941
+ padding: 2px;
1942
+ border: 1px solid var(--line);
1943
+ border-radius: 999px;
1944
+ background: #fafafa;
1945
+ }
1946
+ .workspace-toggle-btn {
1947
+ padding: 4px 13px;
1948
+ border: 0;
1949
+ border-radius: 999px;
1950
+ background: transparent;
1951
+ color: var(--muted);
1952
+ font-family: var(--sans);
1953
+ font-size: 12px;
1954
+ font-weight: 600;
1955
+ cursor: pointer;
1956
+ }
1957
+ .workspace-toggle-btn:hover {
1958
+ color: var(--accent-strong);
1959
+ }
1960
+ .workspace-toggle-btn.is-active {
1961
+ background: var(--accent);
1962
+ color: #ffffff;
1963
+ }
1964
+ .workspace-group + .workspace-group {
1965
+ margin-top: 18px;
1966
+ }
1967
+ .workspace-group-head,
1968
+ .workspace-hub-group-head {
1969
+ display: flex;
1970
+ align-items: center;
1971
+ gap: 8px;
1972
+ margin: 0;
1973
+ padding: 8px 13px;
1974
+ background: #fafafa;
1975
+ border-bottom: 1px solid var(--line);
1976
+ color: var(--ink);
1977
+ font-family: var(--sans);
1978
+ font-size: 12px;
1979
+ font-weight: 650;
1980
+ text-transform: capitalize;
1981
+ }
1982
+ .workspace-group-count,
1983
+ .workspace-hub-count {
1984
+ padding: 0 7px;
1985
+ border-radius: 999px;
1986
+ background: var(--accent-soft);
1987
+ color: var(--accent-strong);
1988
+ font-family: var(--mono);
1989
+ font-size: 10.5px;
1990
+ }
1991
+ .workspace-group {
1992
+ overflow: hidden;
1993
+ border: 1px solid var(--line);
1994
+ border-radius: 11px;
1995
+ background: rgba(255, 255, 255, 0.92);
1996
+ }
1997
+
1998
+ .workspace-hub {
1999
+ margin-top: 28px;
2000
+ }
2001
+ .workspace-hub-title {
2002
+ margin: 0 0 14px;
2003
+ font-family: var(--sans);
2004
+ font-size: 16px;
2005
+ font-weight: 700;
2006
+ color: var(--ink);
2007
+ }
2008
+ .workspace-hub-group {
2009
+ overflow: hidden;
2010
+ border: 1px solid var(--line);
2011
+ border-radius: 11px;
2012
+ background: rgba(255, 255, 255, 0.92);
2013
+ }
2014
+ .workspace-hub-group + .workspace-hub-group {
2015
+ margin-top: 14px;
2016
+ }
2017
+ .workspace-hub-list {
2018
+ display: flex;
2019
+ flex-direction: column;
2020
+ }
2021
+ .workspace-hub-link {
2022
+ padding: 9px 13px;
2023
+ color: var(--accent-strong);
2024
+ font-family: var(--mono);
2025
+ font-size: 12px;
2026
+ text-decoration: none;
2027
+ overflow: hidden;
2028
+ text-overflow: ellipsis;
2029
+ white-space: nowrap;
2030
+ }
2031
+ .workspace-hub-link + .workspace-hub-link {
2032
+ border-top: 1px solid var(--line);
2033
+ }
2034
+ .workspace-hub-link:hover {
2035
+ background: var(--accent-soft);
2036
+ text-decoration: underline;
2037
+ }
2038
+
2039
+ /* --- UI nits --- */
2040
+ /* Flush group headers: #page h3/h2 (ID selectors) otherwise inject a top margin
2041
+ that, with overflow:hidden on the card, shows as whitespace above "Jobs" etc. */
2042
+ #page .workspace-hub-title {
2043
+ margin: 0 0 14px;
2044
+ }
2045
+ #page .workspace-hub-group-head,
2046
+ #page .workspace-group-head {
2047
+ margin: 0;
2048
+ }
2049
+ /* HF brand logo before the "Hugging Face artifacts" heading */
2050
+ .workspace-hub-title {
2051
+ display: flex;
2052
+ align-items: center;
2053
+ gap: 9px;
2054
+ }
2055
+ .workspace-hub-logo {
2056
+ width: 22px;
2057
+ height: 22px;
2058
+ flex: none;
2059
+ }
2060
+ /* Center empty-state placeholders (heading, body, command) */
2061
+ .view-empty {
2062
+ display: flex;
2063
+ flex-direction: column;
2064
+ align-items: center;
2065
+ }
2066
+ #page .view-empty h2,
2067
+ #page .view-empty p {
2068
+ text-align: center;
2069
+ }
2070
+
2071
+ @media (max-width: 720px) {
2072
+ #app {
2073
+ flex-direction: column;
2074
+ }
2075
+ #sidebar {
2076
+ width: 100%;
2077
+ flex: none;
2078
+ height: auto;
2079
+ position: static;
2080
+ }
2081
  #content {
2082
  display: block;
2083
  width: 100%;
2084
  padding: 28px 20px 80px;
2085
  overflow-x: hidden;
2086
  }
2087
+ #view-tabs {
2088
+ margin: 0 0 20px;
2089
+ gap: 18px;
2090
+ justify-content: flex-start;
2091
+ overflow-x: auto;
2092
+ }
2093
+ #view-tabs a {
2094
+ flex: 0 0 auto;
2095
+ }
2096
+ .trace-timeline::before {
2097
+ left: 16px;
2098
+ }
2099
+ .trace-entry {
2100
+ grid-template-columns: 32px minmax(0, 1fr);
2101
+ margin-left: calc(var(--trace-depth) * 10px);
2102
+ }
2103
+ .trace-rail {
2104
+ padding: 0;
2105
+ }
2106
+ .trace-number,
2107
+ .trace-elapsed {
2108
+ display: none;
2109
+ }
2110
+ .trace-dot {
2111
+ top: 10px;
2112
+ right: 10px;
2113
+ }
2114
+ .workspace-file {
2115
+ grid-template-columns: minmax(150px, 1fr) 66px 34px;
2116
+ }
2117
+ .workspace-file-size,
2118
+ .workspace-file-time {
2119
+ display: none;
2120
+ }
2121
  #page {
2122
  width: 100%;
2123
  max-width: 100%;
2124
  }
2125
+ #page h1,
2126
+ #logbook-title {
2127
  font-size: 30px;
2128
  }
2129
  .cell-head {
logbook.js CHANGED
@@ -4,9 +4,12 @@
4
  let MANIFEST = null;
5
  const PAGE_CACHE = {};
6
  const UNFURL_CACHE = {};
 
7
  const LIVE_RELOAD_MS = 1500;
8
  const FIGURE_FRAME_WINDOWS = new Set();
9
  let FIGURE_NAVIGATION_READY = false;
 
 
10
 
11
  function esc(s) {
12
  return String(s)
@@ -286,6 +289,10 @@
286
  /(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/
287
  );
288
  if (chip && uri) chip.dataset.resUrl = uri[1];
 
 
 
 
289
  } else if (meta.type === "dashboard") {
290
  const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
291
  cell.dataset.resUrl = sp
@@ -495,7 +502,7 @@
495
  if (!message || message.type !== "trackio-logbook:navigate") return;
496
  const target = String(message.target || "").replace(/^#?\//, "");
497
  if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return;
498
- const hash = "#/" + target;
499
  if (location.hash === hash) scrollToHash();
500
  else location.hash = hash;
501
  });
@@ -507,6 +514,15 @@
507
  '<path d="M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5"/>' +
508
  '<path d="M3 8 8 3M16 3l5 5M21 16l-5 5M8 21l-5-5"/></svg>';
509
 
 
 
 
 
 
 
 
 
 
510
  // Figures are rendered in same-origin iframes, so fullscreen the fitted
511
  // wrapper rather than the iframe document. This uses the browser's native
512
  // fullscreen UI and preserves the figure's existing responsive sizing.
@@ -635,13 +651,38 @@
635
  ? `<span class="out-artifact-state open">Open ↗</span>`
636
  : `<span class="out-artifact-state">publish to share</span>`;
637
  const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state;
 
638
  el.innerHTML =
639
- `<span class="out-artifact-ico">${ARTIFACT_ICON_IMG}</span>` +
640
  `<span class="out-artifact-name">${esc(info.name)}</span>` +
641
  `<span class="out-artifact-meta">${meta}</span>`;
642
  return el;
643
  }
644
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  function renderCodeCell(body, container, artifacts) {
646
  const parts = parseFences(body);
647
  const block = document.createElement("div");
@@ -694,7 +735,13 @@
694
  embedTexts.push(part.text);
695
  return;
696
  }
697
- inputBody.appendChild(renderCode(part.text, part.lang, part.title));
 
 
 
 
 
 
698
  });
699
  if (artifacts && artifacts.length) {
700
  ensureOut();
@@ -913,13 +960,13 @@
913
  return btn;
914
  }
915
 
916
- function renderCode(code, lang, title) {
917
  const pre = document.createElement("pre");
918
  pre.className = "hl";
919
  const c = document.createElement("code");
920
  c.innerHTML = highlightCode(code, lang);
921
  pre.appendChild(c);
922
- if (!title) {
923
  const wrap = document.createElement("div");
924
  wrap.className = "snippet";
925
  wrap.appendChild(pre);
@@ -983,7 +1030,7 @@
983
  });
984
  }
985
 
986
- /* -------------------- resources rail -------------------- */
987
 
988
  function fmt(n) {
989
  if (n == null) return null;
@@ -1011,18 +1058,6 @@
1011
  const ARTIFACT_ICON_IMG = `<img class="art-ico" src="./bucket-icon.svg" alt="" />`;
1012
  const DASHBOARD_ICON_IMG = `<img class="art-ico" src="./trackio-logo-light.png" alt="" />`;
1013
 
1014
- const RESOURCE_DESC = {
1015
- dashboard: "Dashboard",
1016
- model: "Model",
1017
- dataset: "Dataset",
1018
- space: "Space",
1019
- artifact: "Artifact — in Bucket",
1020
- paper: "Paper",
1021
- repo: "Repository",
1022
- job: "Job — status & logs",
1023
- bucket: "Bucket — artifacts & data",
1024
- };
1025
-
1026
  const HF_NON_MODEL_PREFIX =
1027
  /^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/;
1028
 
@@ -1030,6 +1065,23 @@
1030
  return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
1031
  }
1032
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
  function classifyResource(url) {
1034
  if (IMG_URL.test(url)) {
1035
  return null;
@@ -1059,29 +1111,39 @@
1059
  local: true,
1060
  };
1061
  }
1062
- if ((m = url.match(/huggingface\.co\/buckets\/[^#\s]+#(.+)/))) {
1063
- return { kind: "artifact", id: decodeURIComponent(m[1]), url };
 
1064
  }
1065
- if (/huggingface\.co\/datasets\/[^/]+\/[^/]+/.test(url)) {
1066
- return { kind: "dataset", id: hfId(url, "/datasets/"), url };
 
 
1067
  }
1068
- if (/huggingface\.co\/spaces\/[^/]+\/[^/]+/.test(url)) {
1069
- return { kind: "space", id: hfId(url, "/spaces/"), url };
 
 
1070
  }
1071
  if (/huggingface\.co\/jobs\//.test(url)) {
1072
- const parts = hfId(url, "/jobs/").split("/");
1073
- const jid = parts[1] || "";
 
1074
  return {
1075
  kind: "job",
1076
- id: parts[0] + (jid ? ` · ${jid.slice(0, 12)}${jid.length > 12 ? "…" : ""}` : ""),
1077
  url,
1078
  };
1079
  }
1080
  if (/huggingface\.co\/buckets\//.test(url)) {
1081
- return { kind: "bucket", id: hfId(url, "/buckets/"), url };
 
 
1082
  }
1083
  if (/huggingface\.co\/papers\//.test(url)) {
1084
- return { kind: "paper", id: `Paper ${hfId(url, "/papers/")}`, url };
 
 
1085
  }
1086
  if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) {
1087
  return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url };
@@ -1091,324 +1153,13 @@
1091
  }
1092
  if ((m = url.match(/huggingface\.co\/([^?#]+)/))) {
1093
  const rest = m[1].replace(/\/$/, "");
1094
- if (/^[^/]+\/[^/]+$/.test(rest) && !HF_NON_MODEL_PREFIX.test(rest)) {
1095
  return { kind: "model", id: rest, url };
1096
  }
1097
  }
1098
  return null;
1099
  }
1100
 
1101
- async function fillRailMeta(item, el) {
1102
- if (item.local) return;
1103
- const meta = el.querySelector(".rail-meta");
1104
- const set = (parts) => {
1105
- const text = parts.filter(Boolean).join(" · ");
1106
- if (text) meta.textContent = text;
1107
- };
1108
- if (item.kind === "model") {
1109
- const d = await getJSON(`https://huggingface.co/api/models/${item.id}`);
1110
- if (d) set([d.pipeline_tag, `↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]);
1111
- } else if (item.kind === "dataset") {
1112
- const d = await getJSON(`https://huggingface.co/api/datasets/${item.id}`);
1113
- if (d) set([`↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]);
1114
- } else if (item.kind === "space" || item.kind === "dashboard") {
1115
- const d = await getJSON(`https://huggingface.co/api/spaces/${item.id}`);
1116
- if (d) set([d.sdk, `♥ ${fmt(d.likes)}`]);
1117
- } else if (item.kind === "repo") {
1118
- const d = await getJSON(`https://api.github.com/repos/${item.id}`);
1119
- if (d) set([`★ ${fmt(d.stargazers_count)}`, d.language]);
1120
- } else if (item.kind === "paper") {
1121
- const m = item.id.match(/^(?:arXiv:|Paper )(.+)$/);
1122
- if (!m) return;
1123
- const arxivId = m[1].replace(/v\d+$/, "");
1124
- const d = await getJSON(`https://huggingface.co/api/papers/${arxivId}`);
1125
- if (d && d.id) {
1126
- if (el.href) el.href = `https://huggingface.co/papers/${d.id}`;
1127
- const title =
1128
- d.title && d.title.length > 70 ? `${d.title.slice(0, 69)}…` : d.title;
1129
- set([title, d.upvotes ? `��� ${fmt(d.upvotes)}` : null]);
1130
- }
1131
- }
1132
- }
1133
-
1134
- const BARE_ID_SKIP_DIRS = new Set([
1135
- "scripts",
1136
- "configs",
1137
- "config",
1138
- "results",
1139
- "figures",
1140
- "data",
1141
- "datasets",
1142
- "src",
1143
- "tests",
1144
- "test",
1145
- "examples",
1146
- "pages",
1147
- "assets",
1148
- "docs",
1149
- "outputs",
1150
- "output",
1151
- "checkpoints",
1152
- "models",
1153
- "utils",
1154
- "lib",
1155
- "bin",
1156
- "tmp",
1157
- "node_modules",
1158
- "dist",
1159
- "build",
1160
- ]);
1161
- const FILE_EXT_RE =
1162
- /\.(py|pyc|js|ts|jsx|tsx|json|jsonl|yaml|yml|csv|tsv|md|txt|sh|bash|html|css|png|jpe?g|svg|gif|webp|ipynb|toml|cfg|ini|lock|pdf|whl|gz|zip|tar|pt|pth|bin|safetensors|db|sqlite)$/i;
1163
-
1164
- async function detectBareModelIds(text, groups) {
1165
- const stripped = text.replace(DETECTED_URL, " ");
1166
- DETECTED_URL.lastIndex = 0;
1167
- const seen = new Set();
1168
- const candidates = [];
1169
- const re = /(^|[\s"'`(=[])([A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*)/g;
1170
- let m;
1171
- while ((m = re.exec(stripped)) && candidates.length < 15) {
1172
- const id = m[2].replace(/[.:,]+$/, "");
1173
- if (seen.has(id)) continue;
1174
- seen.add(id);
1175
- if (FILE_EXT_RE.test(id)) continue;
1176
- if (BARE_ID_SKIP_DIRS.has(id.split("/")[0].toLowerCase())) continue;
1177
- candidates.push(id);
1178
- }
1179
- const results = await Promise.all(
1180
- candidates.map((id) => getJSON(`https://huggingface.co/api/models/${id}`))
1181
- );
1182
- let added = false;
1183
- const confirmed = [];
1184
- results.forEach((d, i) => {
1185
- if (!d || !d.id) return;
1186
- const id = candidates[i];
1187
- confirmed.push(id);
1188
- const url = `https://huggingface.co/${id}`;
1189
- if (!groups.has("model")) groups.set("model", new Map());
1190
- if (!groups.get("model").has(url)) {
1191
- groups.get("model").set(url, { kind: "model", id, url });
1192
- added = true;
1193
- }
1194
- });
1195
- return { added, confirmed };
1196
- }
1197
-
1198
- function chipifyBareIds(ids, container) {
1199
- if (!ids.length) return;
1200
- const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
1201
- const pattern = new RegExp("(" + escaped.join("|") + ")");
1202
- const splitter = new RegExp(pattern.source, "g");
1203
- container
1204
- .querySelectorAll(".cell.markdown .cell-body")
1205
- .forEach((body) => {
1206
- const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, {
1207
- acceptNode(node) {
1208
- if (!pattern.test(node.nodeValue)) return NodeFilter.FILTER_REJECT;
1209
- for (
1210
- let el = node.parentElement;
1211
- el && el !== body;
1212
- el = el.parentElement
1213
- ) {
1214
- if (["A", "CODE", "PRE", "BUTTON"].indexOf(el.tagName) !== -1) {
1215
- return NodeFilter.FILTER_REJECT;
1216
- }
1217
- }
1218
- return NodeFilter.FILTER_ACCEPT;
1219
- },
1220
- });
1221
- const nodes = [];
1222
- while (walker.nextNode()) nodes.push(walker.currentNode);
1223
- nodes.forEach((node) => {
1224
- const frag = document.createDocumentFragment();
1225
- node.nodeValue.split(splitter).forEach((part) => {
1226
- if (ids.indexOf(part) !== -1) {
1227
- const holder = document.createElement("span");
1228
- holder.innerHTML = resChipHtml({
1229
- kind: "model",
1230
- id: part,
1231
- url: `https://huggingface.co/${part}`,
1232
- });
1233
- frag.appendChild(holder.firstChild);
1234
- } else if (part) {
1235
- frag.appendChild(document.createTextNode(part));
1236
- }
1237
- });
1238
- node.parentNode.replaceChild(frag, node);
1239
- });
1240
- });
1241
- }
1242
-
1243
- let RAIL_TOKEN = 0;
1244
- const RAIL_EXCLUDE_KINDS = new Set(["paper", "repo", "artifact", "dashboard"]);
1245
-
1246
- function railDashboardItem(it) {
1247
- return {
1248
- kind: "dashboard",
1249
- id: it.id,
1250
- url: it.local ? it.resUrl : it.url || it.resUrl,
1251
- local: it.local,
1252
- railLabel: "Dashboard",
1253
- };
1254
- }
1255
-
1256
- function promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token) {
1257
- const spaceGroup = groups.get("space");
1258
- if (!spaceGroup || !spaceGroup.size) return;
1259
- spaceGroup.forEach((item, url) => {
1260
- getJSON(`https://huggingface.co/api/spaces/${item.id}`)
1261
- .then((d) => {
1262
- if (rail.dataset.renderToken !== token) return;
1263
- const tags = (d && d.tags) || [];
1264
- if (!tags.some((t) => String(t).toLowerCase() === "trackio")) return;
1265
- if (dashResUrls.has(url)) return;
1266
- spaceGroup.delete(url);
1267
- if (!spaceGroup.size) groups.delete("space");
1268
- if (!groups.has("dashboard")) groups.set("dashboard", new Map());
1269
- groups.get("dashboard").set(url, {
1270
- kind: "dashboard",
1271
- id: item.id,
1272
- url: item.url,
1273
- local: false,
1274
- railLabel: "Dashboard",
1275
- });
1276
- dashResUrls.add(url);
1277
- paintRail(groups, body, rail);
1278
- })
1279
- .catch(() => {});
1280
- });
1281
- }
1282
-
1283
- function renderRail(md, body, rail) {
1284
- const token = String(++RAIL_TOKEN);
1285
- rail.dataset.renderToken = token;
1286
- const scanText = md.replace(
1287
- /(`{3,4}|~{3,4})(html|raw)[^\n]*\n[\s\S]*?\n\1/g,
1288
- " "
1289
- );
1290
- const groups = new Map();
1291
- const dashMap = new Map();
1292
- const dashResUrls = new Set();
1293
- cellDashboardItems(md).forEach((it) => {
1294
- if (dashMap.has(it.resUrl)) return;
1295
- dashMap.set(it.resUrl, railDashboardItem(it));
1296
- dashResUrls.add(it.resUrl);
1297
- });
1298
- if (dashMap.size) groups.set("dashboard", dashMap);
1299
- extractUrls(scanText).forEach((url) => {
1300
- const item = classifyResource(url);
1301
- if (!item) return;
1302
- if (RAIL_EXCLUDE_KINDS.has(item.kind)) return;
1303
- if (dashResUrls.has(url)) return;
1304
- if (!groups.has(item.kind)) groups.set(item.kind, new Map());
1305
- groups.get(item.kind).set(item.url, item);
1306
- });
1307
- const artMap = new Map();
1308
- cellArtifactItems(md).forEach((it) => {
1309
- if (artMap.has(it.resUrl)) return;
1310
- const label = it.type
1311
- ? it.type.charAt(0).toUpperCase() + it.type.slice(1)
1312
- : "Artifact";
1313
- artMap.set(it.resUrl, {
1314
- kind: "artifact",
1315
- id: it.name,
1316
- url: it.local ? it.resUrl : it.url || it.resUrl,
1317
- local: it.local,
1318
- railLabel: label,
1319
- size: it.size,
1320
- });
1321
- });
1322
- if (artMap.size) groups.set("artifact", artMap);
1323
- paintRail(groups, body, rail);
1324
- promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token);
1325
- detectBareModelIds(scanText, groups)
1326
- .then((result) => {
1327
- if (rail.dataset.renderToken !== token) return;
1328
- chipifyBareIds(result.confirmed, body);
1329
- if (result.added) paintRail(groups, body, rail);
1330
- })
1331
- .catch(() => {});
1332
- }
1333
-
1334
- function paintRail(groups, body, rail) {
1335
- rail.innerHTML = "";
1336
- RESOURCE_SECTIONS.forEach(([kind, label, icon]) => {
1337
- const group = groups.get(kind);
1338
- if (!group || !group.size) return;
1339
- group.forEach((item) => {
1340
- const el = document.createElement(item.local ? "div" : "a");
1341
- el.className = item.local ? "rail-item rail-local" : "rail-item";
1342
- if (!item.local) {
1343
- el.href = item.url;
1344
- el.target = "_blank";
1345
- el.rel = "noopener";
1346
- }
1347
- el.dataset.resUrl = item.url;
1348
- let desc;
1349
- if (kind === "artifact") {
1350
- const state = item.local ? "publish to share" : "Open ↗";
1351
- desc = item.size ? `${item.size} · ${state}` : state;
1352
- } else if (kind === "dashboard") {
1353
- desc = item.local ? "publish to share" : "Open ↗";
1354
- } else {
1355
- desc = item.local ? "publish to share" : RESOURCE_DESC[kind];
1356
- }
1357
- const kindLabel = item.railLabel || label.replace(/s$/, "");
1358
- const iconHtml =
1359
- kind === "artifact"
1360
- ? ARTIFACT_ICON_IMG
1361
- : kind === "dashboard"
1362
- ? DASHBOARD_ICON_IMG
1363
- : `<span>${icon}</span>`;
1364
- el.innerHTML =
1365
- `<div class="rail-kind">${iconHtml}${esc(kindLabel)}</div>` +
1366
- `<div class="rail-title">${esc(item.id)}</div>` +
1367
- `<div class="rail-meta">${esc(desc)}</div>`;
1368
- rail.appendChild(el);
1369
- fillRailMeta(item, el)
1370
- .catch(() => {})
1371
- .finally(() => scheduleRailPosition(body, rail));
1372
- });
1373
- });
1374
- rail.hidden = !rail.childElementCount;
1375
- scheduleRailPosition(body, rail);
1376
- }
1377
-
1378
- function resourceAnchor(body, url) {
1379
- return body.querySelector(`[data-res-url="${CSS.escape(url)}"]`);
1380
- }
1381
-
1382
- function positionRail(body, rail) {
1383
- if (rail.hidden || !rail.isConnected) return;
1384
- const bodyRect = body.getBoundingClientRect();
1385
- const items = Array.from(rail.querySelectorAll(".rail-item")).map((el, index) => {
1386
- const anchor = resourceAnchor(body, el.dataset.resUrl);
1387
- return {
1388
- el,
1389
- index,
1390
- desired: anchor
1391
- ? Math.max(0, anchor.getBoundingClientRect().top - bodyRect.top)
1392
- : 0,
1393
- };
1394
- });
1395
- items.sort((a, b) => a.desired - b.desired || a.index - b.index);
1396
- let cursor = 0;
1397
- items.forEach(({ el, desired }) => {
1398
- const top = Math.max(desired, cursor);
1399
- el.style.top = `${top}px`;
1400
- cursor = top + el.offsetHeight + 10;
1401
- });
1402
- rail.style.minHeight = `${Math.max(body.offsetHeight, cursor)}px`;
1403
- }
1404
-
1405
- function scheduleRailPosition(body, rail) {
1406
- cancelAnimationFrame(Number(rail.dataset.positionFrame || 0));
1407
- rail.dataset.positionFrame = String(
1408
- requestAnimationFrame(() => positionRail(body, rail))
1409
- );
1410
- }
1411
-
1412
  function dashboardSubdomainFromUrl(url) {
1413
  return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-");
1414
  }
@@ -1523,11 +1274,15 @@
1523
  function buildTree() {
1524
  const tree = document.getElementById("tree");
1525
  tree.innerHTML = "";
 
 
 
 
1526
  const nodes = [];
1527
  (MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes));
1528
  nodes.forEach(({ node, depth }) => {
1529
  const a = document.createElement("a");
1530
- a.href = "#/" + node.slug;
1531
  a.className = "depth-" + depth;
1532
  a.dataset.slug = node.slug;
1533
  const mark = document.createElement("span");
@@ -1539,6 +1294,47 @@
1539
  });
1540
  }
1541
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1542
  function highlight(slug) {
1543
  document
1544
  .querySelectorAll("#tree a")
@@ -1552,6 +1348,9 @@
1552
  Object.keys(PAGE_CACHE).forEach((key) => {
1553
  delete PAGE_CACHE[key];
1554
  });
 
 
 
1555
  }
1556
 
1557
  function isLocalPreview() {
@@ -1577,6 +1376,18 @@
1577
  return PAGE_CACHE[node.file];
1578
  }
1579
 
 
 
 
 
 
 
 
 
 
 
 
 
1580
  function allNodes() {
1581
  const nodes = [];
1582
  flattenTree(MANIFEST.root, 0, nodes);
@@ -1621,13 +1432,28 @@
1621
  cells.forEach(({ meta, body }) => {
1622
  const cell = renderCell(meta, body, list);
1623
  cell.classList.add("pinned-copy");
 
 
1624
  });
1625
  deck.appendChild(list);
1626
  const anchor =
1627
- container.querySelector(".logbook-stats") ||
1628
- container.querySelector(".agent-hint");
1629
  container.insertBefore(deck, anchor ? anchor.nextSibling : container.firstChild);
1630
- container.closest(".book-intro").classList.add("has-pinned-notes");
 
 
 
 
 
 
 
 
 
 
 
 
 
1631
  }
1632
 
1633
  function removeIndexProse(body) {
@@ -1636,7 +1462,11 @@
1636
  let current = h1.nextElementSibling;
1637
  while (current && current.tagName !== "H2") {
1638
  const next = current.nextElementSibling;
1639
- current.remove();
 
 
 
 
1640
  current = next;
1641
  }
1642
  }
@@ -1655,15 +1485,13 @@
1655
  }
1656
  }
1657
 
1658
- const RAIL_OBSERVERS = [];
1659
-
1660
  async function renderLogbook(opts = {}) {
1661
  const scrollY = window.scrollY;
1662
  const page = document.getElementById("page");
1663
- RAIL_OBSERVERS.splice(0).forEach((observer) => observer.disconnect());
1664
  page.innerHTML = "";
1665
  const nodes = allNodes();
1666
  const markdown = await Promise.all(nodes.map(fetchPage));
 
1667
  const pinnedCells = collectPinnedCells(markdown, nodes);
1668
  let bookIntroBody = null;
1669
  nodes.forEach((node, index) => {
@@ -1676,45 +1504,42 @@
1676
  layout.className = "page-layout";
1677
  const body = document.createElement("div");
1678
  body.className = "page-body";
1679
- const rail = document.createElement("aside");
1680
- rail.className = "context-rail";
1681
- rail.setAttribute("aria-label", `Resources for ${node.title}`);
1682
 
1683
  renderMarkdown(markdown[index], body);
1684
  if (node.slug === MANIFEST.root.slug) {
1685
  section.classList.add("book-intro");
1686
  removeIndexProse(body);
1687
  removePageDirectory(body);
1688
- const hint = buildAgentHint();
1689
  const h1 = body.querySelector("h1");
1690
- if (h1 && h1.parentNode === body) {
1691
- body.insertBefore(hint, h1.nextSibling);
1692
- } else {
1693
- body.prepend(hint);
1694
- }
1695
- hint.after(buildLogbookStats(markdown));
1696
  bookIntroBody = body;
1697
  }
1698
  layout.appendChild(body);
1699
- layout.appendChild(rail);
1700
  section.appendChild(layout);
1701
  page.appendChild(section);
1702
- renderRail(markdown[index], body, rail);
1703
- if (window.ResizeObserver) {
1704
- const observer = new ResizeObserver(() => scheduleRailPosition(body, rail));
1705
- observer.observe(body);
1706
- observer.observe(rail);
1707
- RAIL_OBSERVERS.push(observer);
1708
- }
1709
  });
1710
- if (bookIntroBody) renderPinnedNotes(pinnedCells, bookIntroBody);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1711
  if (bookIntroBody) {
1712
  const section = bookIntroBody.closest(".book-intro");
1713
  const hasExtra = Array.from(bookIntroBody.children).some(
1714
  (el) =>
1715
  el.tagName !== "H1" &&
1716
  !el.classList.contains("agent-hint") &&
1717
- !el.classList.contains("logbook-stats") &&
1718
  !el.classList.contains("pinned-notes")
1719
  );
1720
  if (section && !section.classList.contains("has-pinned-notes") && !hasExtra) {
@@ -1731,29 +1556,6 @@
1731
  });
1732
  }
1733
 
1734
- function setupResourceHover() {
1735
- document.addEventListener("mouseover", (e) => {
1736
- const el = e.target.closest && e.target.closest("[data-res-url]");
1737
- if (!el || el.classList.contains("rail-item")) return;
1738
- const url = el.getAttribute("data-res-url");
1739
- const section = el.closest(".page-section");
1740
- const scope = section || document;
1741
- scope.querySelectorAll(".context-rail [data-res-url]").forEach((n) => {
1742
- n.classList.toggle("res-hl", n.getAttribute("data-res-url") === url);
1743
- });
1744
- });
1745
- document.addEventListener("mouseout", (e) => {
1746
- const el = e.target.closest && e.target.closest("[data-res-url]");
1747
- if (!el || el.classList.contains("rail-item")) return;
1748
- document.querySelectorAll(".context-rail .res-hl").forEach((n) => {
1749
- n.classList.remove("res-hl");
1750
- });
1751
- });
1752
- }
1753
-
1754
- let STATS_TOKEN = 0;
1755
- let STATS_LISTENERS = false;
1756
-
1757
  function fmtBytes(n) {
1758
  if (n == null || isNaN(n)) return null;
1759
  if (n < 1000) return `${n} B`;
@@ -1771,31 +1573,6 @@
1771
  return url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
1772
  }
1773
 
1774
- const LB_CELL_RE = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
1775
-
1776
- function cellDashboardItems(md) {
1777
- const re = new RegExp(LB_CELL_RE.source, "g");
1778
- const items = [];
1779
- let m;
1780
- while ((m = re.exec(md))) {
1781
- const meta = parseCellMeta(m[2]);
1782
- if (meta.type !== "dashboard") continue;
1783
- const body = m[3];
1784
- const project = meta.dashboard_project || "";
1785
- const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
1786
- const local = !sp;
1787
- const url = sp ? sp[0] : "";
1788
- const resUrl = local ? `trackio-local-dashboard://${project}` : url;
1789
- items.push({
1790
- id: local ? project : spaceIdFromUrl(url),
1791
- local,
1792
- url,
1793
- resUrl,
1794
- });
1795
- }
1796
- return items;
1797
- }
1798
-
1799
  function artifactInfoFromCell(meta, body) {
1800
  const name = meta.artifact || meta.path || "";
1801
  let size = null;
@@ -1820,280 +1597,1036 @@
1820
  };
1821
  }
1822
 
1823
- function cellArtifactItems(md) {
1824
- const re = new RegExp(LB_CELL_RE.source, "g");
1825
- const items = [];
1826
- let m;
1827
- while ((m = re.exec(md))) {
1828
- const meta = parseCellMeta(m[2]);
1829
- const body = m[3];
1830
- const order = meta.created_at || "";
1831
- if (meta.type === "artifact") {
1832
- const info = artifactInfoFromCell(meta, body);
1833
- if (info.name) items.push({ ...info, order });
1834
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1835
  }
1836
- return items;
1837
- }
1838
-
1839
- function collectLogbookResources(markdownList) {
1840
- const re = new RegExp(LB_CELL_RE.source, "g");
1841
- const dashboards = new Map();
1842
- markdownList.forEach((md) => {
1843
- let m;
1844
- while ((m = re.exec(md))) {
1845
- const meta = parseCellMeta(m[2]);
1846
- const body = m[3];
1847
- if (meta.type !== "dashboard") continue;
1848
- const project = meta.dashboard_project || "";
1849
- const space = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
1850
- const local = !space;
1851
- const url = space ? space[0] : "";
1852
- const key = local ? `local:${project}` : `space:${spaceIdFromUrl(url)}`;
1853
- const resUrl = local ? `trackio-local-dashboard://${project}` : url;
1854
- if (!dashboards.has(key))
1855
- dashboards.set(key, { project, local, url, resUrl });
1856
  }
1857
- });
1858
- const artifacts = new Map();
1859
- markdownList.forEach((md) => {
1860
- cellArtifactItems(md).forEach((it) => {
1861
- const key = `${it.type}:${it.name}`;
1862
- const prev = artifacts.get(key);
1863
- if (!prev || it.order >= prev.order) artifacts.set(key, it);
1864
- });
1865
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1866
  return {
1867
- dashboards: Array.from(dashboards.values()).sort((a, b) =>
1868
- a.project.localeCompare(b.project)
1869
- ),
1870
- artifacts: Array.from(artifacts.values()).sort((a, b) =>
1871
- a.name.localeCompare(b.name)
1872
- ),
1873
  };
1874
  }
1875
 
1876
- function closeStatPopovers() {
1877
- document
1878
- .querySelectorAll(".stat-popover")
1879
- .forEach((p) => (p.hidden = true));
1880
- document
1881
- .querySelectorAll(".stat-tile.open")
1882
- .forEach((t) => t.classList.remove("open"));
 
 
 
 
 
1883
  }
1884
 
1885
- function ensureStatListeners() {
1886
- if (STATS_LISTENERS) return;
1887
- STATS_LISTENERS = true;
1888
- document.addEventListener("click", closeStatPopovers);
1889
- document.addEventListener("keydown", (e) => {
1890
- if (e.key === "Escape") closeStatPopovers();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1891
  });
1892
  }
1893
 
1894
- function stateHtml(remote, url) {
1895
- return remote
1896
- ? `<a class="stat-row-state open" href="${esc(url)}" target="_blank" rel="noopener" title="Open in a new tab">Open ↗</a>`
1897
- : `<span class="stat-row-state">publish to share</span>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1898
  }
1899
 
1900
- function scrollToResource(resUrl) {
1901
- closeStatPopovers();
1902
- if (!resUrl) return;
1903
- const el = document.querySelector(
1904
- `#page .page-body [data-res-url="${CSS.escape(resUrl)}"]:not(.stat-row)`
1905
- );
1906
- if (!el) return;
1907
- el.scrollIntoView({ behavior: "smooth", block: "center" });
1908
- el.classList.add("res-flash");
1909
- setTimeout(() => el.classList.remove("res-flash"), 1500);
1910
- }
1911
-
1912
- function dashRowHtml(d) {
1913
- const inner =
1914
- `<span class="stat-row-ico">${DASHBOARD_ICON_IMG}</span>` +
1915
- `<div class="stat-row-main"><div class="stat-row-title">${esc(d.project)}</div>` +
1916
- `<div class="stat-row-meta">${stateHtml(!d.local, d.url)}</div></div>`;
1917
- return `<div class="stat-row" data-res-url="${esc(d.resUrl)}" title="Jump to it in the logbook">${inner}</div>`;
1918
- }
1919
-
1920
- function artRowHtml(a) {
1921
- const remote = !a.local && !!a.url;
1922
- const parts = [a.type, a.size].filter(Boolean).map(esc);
1923
- const meta = parts.length
1924
- ? `${parts.join(" · ")} · ${stateHtml(remote, a.url)}`
1925
- : stateHtml(remote, a.url);
1926
- const inner =
1927
- `<span class="stat-row-ico">${ARTIFACT_ICON_IMG}</span>` +
1928
- `<div class="stat-row-main"><div class="stat-row-title">${esc(a.name)}</div>` +
1929
- `<div class="stat-row-meta">${meta}</div></div>`;
1930
- return `<div class="stat-row" data-res-url="${esc(a.resUrl)}" title="Jump to it in the logbook">${inner}</div>`;
1931
- }
1932
-
1933
- function statTile(icon, alt, singular, plural, head, rowFn) {
1934
- const tile = document.createElement("button");
1935
- tile.type = "button";
1936
- tile.className = "stat-tile";
1937
- const render = (items) => {
1938
- const count = items.length;
1939
- const label = count === 1 ? singular : plural;
1940
- const caret = count > 0 ? `<span class="stat-caret">▾</span>` : "";
1941
- tile.innerHTML =
1942
- `<img class="stat-icon" src="${icon}" alt="${esc(alt)}" />` +
1943
- `<div class="stat-text"><div class="stat-num">${count}</div>` +
1944
- `<div class="stat-label">${esc(label)}</div></div>` +
1945
- caret;
1946
- tile.disabled = count === 0;
1947
- if (count > 0) {
1948
- const pop = document.createElement("div");
1949
- pop.className = "stat-popover";
1950
- pop.hidden = true;
1951
- pop.innerHTML =
1952
- `<div class="stat-pop-head">${esc(head)}</div>` +
1953
- items.map(rowFn).join("");
1954
- pop.addEventListener("click", (e) => {
1955
- if (e.target.closest("a.stat-row-state")) {
1956
- e.stopPropagation();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1957
  return;
1958
  }
1959
- e.stopPropagation();
1960
- const row = e.target.closest(".stat-row");
1961
- if (row) scrollToResource(row.dataset.resUrl);
 
 
1962
  });
1963
- tile.appendChild(pop);
1964
- }
1965
- };
1966
- tile.addEventListener("click", (e) => {
1967
- if (tile.disabled) return;
1968
- e.stopPropagation();
1969
- const pop = tile.querySelector(".stat-popover");
1970
- if (!pop) return;
1971
- const isOpen = !pop.hidden;
1972
- closeStatPopovers();
1973
- if (!isOpen) {
1974
- pop.hidden = false;
1975
- tile.classList.add("open");
1976
  }
1977
- });
1978
- return { tile, render };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1979
  }
1980
 
1981
- function buildLogbookStats(markdownList) {
1982
- const token = ++STATS_TOKEN;
1983
- ensureStatListeners();
1984
- const { dashboards, artifacts } = collectLogbookResources(markdownList);
 
 
 
 
 
1985
 
1986
- const el = document.createElement("div");
1987
- el.className = "logbook-stats";
1988
- const dash = statTile(
1989
- "./trackio-logo-light.png",
1990
- "Trackio",
1991
- "Trackio Dashboard",
1992
- "Trackio Dashboards",
1993
- "Dashboards created in this logbook",
1994
- dashRowHtml
1995
- );
1996
- const art = statTile(
1997
- "./bucket-icon.svg",
1998
- "Bucket",
1999
- "Artifact",
2000
- "Artifacts",
2001
- "Artifacts created in this logbook",
2002
- artRowHtml
2003
- );
2004
- dash.render(dashboards);
2005
- art.render(artifacts);
2006
- el.appendChild(dash.tile);
2007
- el.appendChild(art.tile);
2008
-
2009
- const scanText = markdownList
2010
- .map((md) =>
2011
- md.replace(/(`{3,4}|~{3,4})(html|raw)[^\n]*\n[\s\S]*?\n\1/g, " ")
2012
- )
2013
- .join("\n");
2014
- const seen = new Set(
2015
- dashboards.map((d) =>
2016
- d.local ? `local:${d.project}` : `space:${spaceIdFromUrl(d.url)}`
2017
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2018
  );
2019
- const remoteSpaces = new Map();
2020
- extractUrls(scanText).forEach((url) => {
2021
- const item = classifyResource(url);
2022
- if (item && item.kind === "space" && !item.local) {
2023
- remoteSpaces.set(item.url, item);
 
 
 
 
 
 
 
2024
  }
2025
- });
2026
- remoteSpaces.forEach((s) => {
2027
- const key = `space:${s.id}`;
2028
- if (seen.has(key)) return;
2029
- getJSON(`https://huggingface.co/api/spaces/${s.id}`)
2030
- .then((d) => {
2031
- if (STATS_TOKEN !== token) return;
2032
- const tags = (d && d.tags) || [];
2033
- if (
2034
- !seen.has(key) &&
2035
- tags.some((t) => String(t).toLowerCase() === "trackio")
2036
- ) {
2037
- seen.add(key);
2038
- dashboards.push({
2039
- project: s.id,
2040
- local: false,
2041
- url: s.url,
2042
- resUrl: s.url,
2043
- });
2044
- dashboards.sort((a, b) => a.project.localeCompare(b.project));
2045
- dash.render(dashboards);
2046
- }
2047
  })
2048
- .catch(() => {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2049
  });
2050
- return el;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2051
  }
2052
 
2053
- function buildAgentHint() {
2054
- const onSpaces =
2055
- /\.hf\.space$/.test(location.hostname) ||
2056
- /(^|\.)huggingface\.co$/.test(location.hostname);
2057
- let source = "";
2058
- if (onSpaces && MANIFEST.space_id) {
2059
- source = ` ${MANIFEST.space_id}`;
2060
- } else if (/^https?:$/.test(location.protocol)) {
2061
- source = ` ${location.origin}/`;
2062
- }
2063
- const command = `trackio logbook read${source}`;
2064
- const tokens = MANIFEST.agent_view_tokens;
2065
- const div = document.createElement("div");
2066
- div.className = "agent-hint";
2067
  const label = document.createElement("span");
2068
- label.className = "agent-hint-label";
2069
- label.textContent = "Read from the CLI:";
2070
- const code = document.createElement("code");
2071
- code.textContent = command;
2072
- const copy = document.createElement("button");
2073
- copy.className = "copy";
2074
- copy.type = "button";
2075
- copy.title = "Copy";
2076
- copy.textContent = "";
2077
- copy.addEventListener("click", () => copyText(command, copy, ""));
2078
- const note = document.createElement("span");
2079
- note.className = "agent-hint-note";
2080
- note.textContent =
2081
- "compact view for agents" + (tokens ? ` · ~${fmt(tokens)} tokens` : "");
2082
- div.appendChild(label);
2083
- div.appendChild(code);
2084
- div.appendChild(copy);
2085
- div.appendChild(note);
2086
- return div;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2087
  }
2088
 
2089
  function currentSlug() {
2090
- const slug = (location.hash || "").replace(/^#\//, "") || MANIFEST.root.slug;
2091
- return findNode(MANIFEST.root, slug) ? slug : MANIFEST.root.slug;
2092
  }
2093
 
2094
  function scrollToHash(opts = {}) {
 
2095
  const slug = currentSlug();
2096
- if (!location.hash) {
2097
  window.scrollTo({ top: 0, behavior: opts.behavior || "auto" });
2098
  highlight(slug);
2099
  return;
@@ -2106,7 +2639,7 @@
2106
  function navigateToLogbookSlug(target) {
2107
  const slug = String(target || "").replace(/^#?\//, "").trim();
2108
  if (!slug || !findNode(MANIFEST.root, slug)) return;
2109
- const hash = "#/" + slug;
2110
  if (location.hash === hash) {
2111
  scrollToHash({ behavior: "smooth" });
2112
  } else {
@@ -2130,9 +2663,12 @@
2130
 
2131
  let SCROLL_FRAME = 0;
2132
  function updateActiveSection() {
 
2133
  cancelAnimationFrame(SCROLL_FRAME);
2134
  SCROLL_FRAME = requestAnimationFrame(() => {
2135
- const sections = Array.from(document.querySelectorAll(".page-section"));
 
 
2136
  if (!sections.length) return;
2137
  const marker = Math.min(window.innerHeight * 0.28, 180);
2138
  let active = sections[0];
@@ -2145,7 +2681,11 @@
2145
  ) {
2146
  active = sections[sections.length - 1];
2147
  }
2148
- highlight(active.dataset.slug);
 
 
 
 
2149
  });
2150
  }
2151
 
@@ -2161,7 +2701,7 @@
2161
  document.getElementById("book-title").textContent = MANIFEST.title;
2162
  document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
2163
  buildTree();
2164
- renderLogbook({ preserveScroll: true });
2165
  } catch (e) {}
2166
  }, LIVE_RELOAD_MS);
2167
  }
@@ -2257,17 +2797,16 @@
2257
  document.getElementById("book-title").textContent = MANIFEST.title;
2258
  document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
2259
  document.getElementById("book-head").addEventListener("click", () => {
2260
- const target = "#/" + MANIFEST.root.slug;
2261
  if (location.hash === target) scrollToHash();
2262
  else location.hash = target;
2263
  });
2264
  buildTree();
2265
  setupConnect();
2266
- setupResourceHover();
2267
  setupFigureNavigation();
2268
- window.addEventListener("hashchange", () => scrollToHash());
2269
  window.addEventListener("scroll", updateActiveSection, { passive: true });
2270
- await renderLogbook();
2271
  startLiveReload();
2272
  }
2273
 
 
4
  let MANIFEST = null;
5
  const PAGE_CACHE = {};
6
  const UNFURL_CACHE = {};
7
+ const DATA_CACHE = {};
8
  const LIVE_RELOAD_MS = 1500;
9
  const FIGURE_FRAME_WINDOWS = new Set();
10
  let FIGURE_NAVIGATION_READY = false;
11
+ let CURRENT_VIEW = null;
12
+ let RENDER_SEQUENCE = 0;
13
 
14
  function esc(s) {
15
  return String(s)
 
289
  /(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/
290
  );
291
  if (chip && uri) chip.dataset.resUrl = uri[1];
292
+ if (chip && meta.path) {
293
+ const ico = chip.querySelector(".art-ico");
294
+ if (ico) ico.outerHTML = FILE_ICON;
295
+ }
296
  } else if (meta.type === "dashboard") {
297
  const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
298
  cell.dataset.resUrl = sp
 
502
  if (!message || message.type !== "trackio-logbook:navigate") return;
503
  const target = String(message.target || "").replace(/^#?\//, "");
504
  if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return;
505
+ const hash = "#/view/code/" + target;
506
  if (location.hash === hash) scrollToHash();
507
  else location.hash = hash;
508
  });
 
514
  '<path d="M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5"/>' +
515
  '<path d="M3 8 8 3M16 3l5 5M21 16l-5 5M8 21l-5-5"/></svg>';
516
 
517
+ const PIN_ICON =
518
+ '<svg class="pin-ico" viewBox="0 0 24 24" aria-hidden="true">' +
519
+ '<path d="M16 9V4h1c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1h1v5c0 ' +
520
+ '1.66-1.34 3-3 3v2h5.97v7l1 1 1-1v-7H19v-2c-1.66 0-3-1.34-3-3z"/></svg>';
521
+
522
+ const FILE_ICON =
523
+ '<svg class="art-file-ico" viewBox="0 0 24 24" aria-hidden="true">' +
524
+ '<path d="M6 3.5h8l4 4V20H6zM14 3.5V8h4"/></svg>';
525
+
526
  // Figures are rendered in same-origin iframes, so fullscreen the fitted
527
  // wrapper rather than the iframe document. This uses the browser's native
528
  // fullscreen UI and preserves the figure's existing responsive sizing.
 
651
  ? `<span class="out-artifact-state open">Open ↗</span>`
652
  : `<span class="out-artifact-state">publish to share</span>`;
653
  const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state;
654
+ const icon = info.isPathRef ? FILE_ICON : ARTIFACT_ICON_IMG;
655
  el.innerHTML =
656
+ `<span class="out-artifact-ico">${icon}</span>` +
657
  `<span class="out-artifact-name">${esc(info.name)}</span>` +
658
  `<span class="out-artifact-meta">${meta}</span>`;
659
  return el;
660
  }
661
 
662
+ function isShellCommand(part) {
663
+ return (
664
+ part.kind === "code" &&
665
+ part.lang === "bash" &&
666
+ !part.title &&
667
+ /^\s*\$\s/.test(part.text)
668
+ );
669
+ }
670
+
671
+ function renderCommandLine(text) {
672
+ const command = text.trim().replace(/^\$\s*/, "");
673
+ const el = document.createElement("div");
674
+ el.className = "jp-cmd";
675
+ const prompt = document.createElement("span");
676
+ prompt.className = "jp-cmd-prompt";
677
+ prompt.textContent = "$";
678
+ const code = document.createElement("code");
679
+ code.textContent = command;
680
+ el.appendChild(prompt);
681
+ el.appendChild(code);
682
+ el.appendChild(copySnippetBtn(command));
683
+ return el;
684
+ }
685
+
686
  function renderCodeCell(body, container, artifacts) {
687
  const parts = parseFences(body);
688
  const block = document.createElement("div");
 
735
  embedTexts.push(part.text);
736
  return;
737
  }
738
+ if (isShellCommand(part)) {
739
+ inputBody.appendChild(renderCommandLine(part.text));
740
+ } else {
741
+ inputBody.appendChild(
742
+ renderCode(part.text, part.lang, part.title, Boolean(part.title))
743
+ );
744
+ }
745
  });
746
  if (artifacts && artifacts.length) {
747
  ensureOut();
 
960
  return btn;
961
  }
962
 
963
+ function renderCode(code, lang, title, open) {
964
  const pre = document.createElement("pre");
965
  pre.className = "hl";
966
  const c = document.createElement("code");
967
  c.innerHTML = highlightCode(code, lang);
968
  pre.appendChild(c);
969
+ if (!title || open) {
970
  const wrap = document.createElement("div");
971
  wrap.className = "snippet";
972
  wrap.appendChild(pre);
 
1030
  });
1031
  }
1032
 
1033
+ /* -------------------- resource classification -------------------- */
1034
 
1035
  function fmt(n) {
1036
  if (n == null) return null;
 
1058
  const ARTIFACT_ICON_IMG = `<img class="art-ico" src="./bucket-icon.svg" alt="" />`;
1059
  const DASHBOARD_ICON_IMG = `<img class="art-ico" src="./trackio-logo-light.png" alt="" />`;
1060
 
 
 
 
 
 
 
 
 
 
 
 
 
1061
  const HF_NON_MODEL_PREFIX =
1062
  /^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/;
1063
 
 
1065
  return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
1066
  }
1067
 
1068
+ function validHfSegment(value) {
1069
+ return Boolean(
1070
+ value &&
1071
+ value.length <= 96 &&
1072
+ /^[A-Za-z0-9_.-]+$/.test(value) &&
1073
+ !/^[.-]|[.-]$|--|\.\./.test(value)
1074
+ );
1075
+ }
1076
+
1077
+ function validHfRepoId(parts) {
1078
+ return (
1079
+ parts.length === 2 &&
1080
+ parts.join("/").length <= 96 &&
1081
+ parts.every(validHfSegment)
1082
+ );
1083
+ }
1084
+
1085
  function classifyResource(url) {
1086
  if (IMG_URL.test(url)) {
1087
  return null;
 
1111
  local: true,
1112
  };
1113
  }
1114
+ if ((m = url.match(/huggingface\.co\/buckets\/([^/#\s]+\/[^/#\s]+)#(.+)/))) {
1115
+ if (!validHfRepoId(m[1].split("/"))) return null;
1116
+ return { kind: "artifact", id: decodeURIComponent(m[2]), url };
1117
  }
1118
+ if (/huggingface\.co\/datasets\//.test(url)) {
1119
+ const parts = hfId(url, "/datasets/").split("/").slice(0, 2);
1120
+ if (!validHfRepoId(parts)) return null;
1121
+ return { kind: "dataset", id: parts.join("/"), url };
1122
  }
1123
+ if (/huggingface\.co\/spaces\//.test(url)) {
1124
+ const parts = hfId(url, "/spaces/").split("/").slice(0, 2);
1125
+ if (!validHfRepoId(parts)) return null;
1126
+ return { kind: "space", id: parts.join("/"), url };
1127
  }
1128
  if (/huggingface\.co\/jobs\//.test(url)) {
1129
+ const parts = hfId(url, "/jobs/").split("/").slice(0, 2);
1130
+ if (!validHfRepoId(parts)) return null;
1131
+ const jid = parts[1];
1132
  return {
1133
  kind: "job",
1134
+ id: parts[0] + ` · ${jid.slice(0, 12)}${jid.length > 12 ? "…" : ""}`,
1135
  url,
1136
  };
1137
  }
1138
  if (/huggingface\.co\/buckets\//.test(url)) {
1139
+ const parts = hfId(url, "/buckets/").split("/").slice(0, 2);
1140
+ if (!validHfRepoId(parts)) return null;
1141
+ return { kind: "bucket", id: parts.join("/"), url };
1142
  }
1143
  if (/huggingface\.co\/papers\//.test(url)) {
1144
+ const id = hfId(url, "/papers/").split("/")[0];
1145
+ if (!validHfSegment(id)) return null;
1146
+ return { kind: "paper", id: `Paper ${id}`, url };
1147
  }
1148
  if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) {
1149
  return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url };
 
1153
  }
1154
  if ((m = url.match(/huggingface\.co\/([^?#]+)/))) {
1155
  const rest = m[1].replace(/\/$/, "");
1156
+ if (validHfRepoId(rest.split("/")) && !HF_NON_MODEL_PREFIX.test(rest)) {
1157
  return { kind: "model", id: rest, url };
1158
  }
1159
  }
1160
  return null;
1161
  }
1162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1163
  function dashboardSubdomainFromUrl(url) {
1164
  return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-");
1165
  }
 
1274
  function buildTree() {
1275
  const tree = document.getElementById("tree");
1276
  tree.innerHTML = "";
1277
+ const label = document.createElement("div");
1278
+ label.className = "tree-label";
1279
+ label.textContent = "Pages";
1280
+ tree.appendChild(label);
1281
  const nodes = [];
1282
  (MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes));
1283
  nodes.forEach(({ node, depth }) => {
1284
  const a = document.createElement("a");
1285
+ a.href = "#/view/code/" + node.slug;
1286
  a.className = "depth-" + depth;
1287
  a.dataset.slug = node.slug;
1288
  const mark = document.createElement("span");
 
1294
  });
1295
  }
1296
 
1297
+ function highlightTraceSession(sessionId) {
1298
+ document.querySelectorAll("#tree a").forEach((link) => {
1299
+ link.classList.toggle("active", link.dataset.sessionId === sessionId);
1300
+ });
1301
+ }
1302
+
1303
+ function buildTraceTree(activeSessionId) {
1304
+ const tree = document.getElementById("tree");
1305
+ tree.innerHTML = "";
1306
+ const sessions = MANIFEST.traces || [];
1307
+ if (!sessions.length) return;
1308
+ const label = document.createElement("div");
1309
+ label.className = "tree-label";
1310
+ label.textContent = "Sessions";
1311
+ tree.appendChild(label);
1312
+ sessions.forEach((session) => {
1313
+ const link = document.createElement("a");
1314
+ link.href = "#" + traceSessionAnchor(session.id);
1315
+ link.dataset.sessionId = session.id;
1316
+ link.textContent = session.title || session.id;
1317
+ link.title = session.title || session.id;
1318
+ tree.appendChild(link);
1319
+ });
1320
+ highlightTraceSession(activeSessionId || sessions[0].id);
1321
+ }
1322
+
1323
+ function renderSidebar(route) {
1324
+ if (route.view === "trace") {
1325
+ highlight(null);
1326
+ buildTraceTree(route.sessionId);
1327
+ return;
1328
+ }
1329
+ if (route.view === "workspace") {
1330
+ document.getElementById("tree").innerHTML = "";
1331
+ highlight(null);
1332
+ return;
1333
+ }
1334
+ buildTree();
1335
+ highlight(route.slug);
1336
+ }
1337
+
1338
  function highlight(slug) {
1339
  document
1340
  .querySelectorAll("#tree a")
 
1348
  Object.keys(PAGE_CACHE).forEach((key) => {
1349
  delete PAGE_CACHE[key];
1350
  });
1351
+ Object.keys(DATA_CACHE).forEach((key) => {
1352
+ delete DATA_CACHE[key];
1353
+ });
1354
  }
1355
 
1356
  function isLocalPreview() {
 
1376
  return PAGE_CACHE[node.file];
1377
  }
1378
 
1379
+ async function fetchData(file, cacheResult = true) {
1380
+ if (cacheResult && DATA_CACHE[file]) return DATA_CACHE[file];
1381
+ const suffix = isLocalPreview()
1382
+ ? `?rev=${encodeURIComponent(MANIFEST.revision || "")}`
1383
+ : "";
1384
+ const response = await fetch("./" + file + suffix, { cache: "no-store" });
1385
+ if (!response.ok) throw new Error(`Could not load ${file}`);
1386
+ const data = await response.json();
1387
+ if (cacheResult) DATA_CACHE[file] = data;
1388
+ return data;
1389
+ }
1390
+
1391
  function allNodes() {
1392
  const nodes = [];
1393
  flattenTree(MANIFEST.root, 0, nodes);
 
1432
  cells.forEach(({ meta, body }) => {
1433
  const cell = renderCell(meta, body, list);
1434
  cell.classList.add("pinned-copy");
1435
+ const title = cell.querySelector(".cell-title");
1436
+ if (title) title.insertAdjacentHTML("afterbegin", PIN_ICON);
1437
  });
1438
  deck.appendChild(list);
1439
  const anchor =
1440
+ container.querySelector(".agent-hint") ||
1441
+ Array.from(container.children).find((el) => el.tagName === "H1");
1442
  container.insertBefore(deck, anchor ? anchor.nextSibling : container.firstChild);
1443
+ const owner = container.closest(".page-section");
1444
+ if (owner) owner.classList.add("has-pinned-notes");
1445
+ }
1446
+
1447
+ function isIndexPaperLink(el) {
1448
+ if (!el || el.tagName !== "P") return false;
1449
+ return Array.from(el.querySelectorAll("a[href]")).some((a) => {
1450
+ const href = a.getAttribute("href") || "";
1451
+ return (
1452
+ /huggingface\.co\/papers\//.test(href) ||
1453
+ /openreview\.net\//.test(href) ||
1454
+ /arxiv\.org\//.test(href)
1455
+ );
1456
+ });
1457
  }
1458
 
1459
  function removeIndexProse(body) {
 
1462
  let current = h1.nextElementSibling;
1463
  while (current && current.tagName !== "H2") {
1464
  const next = current.nextElementSibling;
1465
+ if (isIndexPaperLink(current)) {
1466
+ current.classList.add("index-paper-link");
1467
+ } else {
1468
+ current.remove();
1469
+ }
1470
  current = next;
1471
  }
1472
  }
 
1485
  }
1486
  }
1487
 
 
 
1488
  async function renderLogbook(opts = {}) {
1489
  const scrollY = window.scrollY;
1490
  const page = document.getElementById("page");
 
1491
  page.innerHTML = "";
1492
  const nodes = allNodes();
1493
  const markdown = await Promise.all(nodes.map(fetchPage));
1494
+ if (opts.renderId && opts.renderId !== RENDER_SEQUENCE) return;
1495
  const pinnedCells = collectPinnedCells(markdown, nodes);
1496
  let bookIntroBody = null;
1497
  nodes.forEach((node, index) => {
 
1504
  layout.className = "page-layout";
1505
  const body = document.createElement("div");
1506
  body.className = "page-body";
 
 
 
1507
 
1508
  renderMarkdown(markdown[index], body);
1509
  if (node.slug === MANIFEST.root.slug) {
1510
  section.classList.add("book-intro");
1511
  removeIndexProse(body);
1512
  removePageDirectory(body);
 
1513
  const h1 = body.querySelector("h1");
1514
+ if (h1 && h1.parentNode === body) h1.remove();
 
 
 
 
 
1515
  bookIntroBody = body;
1516
  }
1517
  layout.appendChild(body);
 
1518
  section.appendChild(layout);
1519
  page.appendChild(section);
 
 
 
 
 
 
 
1520
  });
1521
+ const pinnedSlugs = Array.from(
1522
+ new Set(pinnedCells.map((cell) => cell.node && cell.node.slug).filter(Boolean))
1523
+ );
1524
+ const pinnedTarget =
1525
+ pinnedSlugs.length === 1
1526
+ ? Array.from(page.querySelectorAll(".page-section"))
1527
+ .find((section) => section.dataset.slug === pinnedSlugs[0])
1528
+ ?.querySelector(".page-body")
1529
+ : bookIntroBody;
1530
+ if (pinnedTarget) renderPinnedNotes(pinnedCells, pinnedTarget);
1531
+ // Pinned cells are promoted into one deck. Remove their source render so
1532
+ // summaries, posters, and notes do not appear twice in the continuous view.
1533
+ page
1534
+ .querySelectorAll(".pinned-source:not(.pinned-copy)")
1535
+ .forEach((cell) => cell.remove());
1536
  if (bookIntroBody) {
1537
  const section = bookIntroBody.closest(".book-intro");
1538
  const hasExtra = Array.from(bookIntroBody.children).some(
1539
  (el) =>
1540
  el.tagName !== "H1" &&
1541
  !el.classList.contains("agent-hint") &&
1542
+ !el.classList.contains("index-paper-link") &&
1543
  !el.classList.contains("pinned-notes")
1544
  );
1545
  if (section && !section.classList.contains("has-pinned-notes") && !hasExtra) {
 
1556
  });
1557
  }
1558
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1559
  function fmtBytes(n) {
1560
  if (n == null || isNaN(n)) return null;
1561
  if (n < 1000) return `${n} B`;
 
1573
  return url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
1574
  }
1575
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1576
  function artifactInfoFromCell(meta, body) {
1577
  const name = meta.artifact || meta.path || "";
1578
  let size = null;
 
1597
  };
1598
  }
1599
 
1600
+ const VIEW_ROUTE = { trace: "#/view/trace", workspace: "#/view/workspace" };
1601
+ const VIEW_TOKENS = {
1602
+ code: "agent_view_tokens",
1603
+ trace: "trace_view_tokens",
1604
+ workspace: "workspace_view_tokens",
1605
+ };
1606
+
1607
+ function readTarget(view) {
1608
+ const onSpaces =
1609
+ /\.hf\.space$/.test(location.hostname) ||
1610
+ /(^|\.)huggingface\.co$/.test(location.hostname);
1611
+ let base = "";
1612
+ if (onSpaces && MANIFEST.space_id) base = MANIFEST.space_id;
1613
+ else if (/^https?:$/.test(location.protocol))
1614
+ base = `${location.origin}${location.pathname}`;
1615
+ if (!base) return "";
1616
+ return base + (VIEW_ROUTE[view] || "");
1617
+ }
1618
+
1619
+ function renderLogbookHeader(view) {
1620
+ const title = document.getElementById("logbook-title");
1621
+ if (title) title.textContent = MANIFEST.title;
1622
+ const cli = document.getElementById("logbook-cli");
1623
+ if (!cli) return;
1624
+ cli.innerHTML = "";
1625
+ cli.appendChild(buildAgentHint(view));
1626
+ const destination = buildHubDestinationLink(view);
1627
+ if (destination) cli.appendChild(destination);
1628
+ }
1629
+
1630
+ function hubDestination(view) {
1631
+ if (view === "trace" && MANIFEST.trace_dataset) {
1632
+ return {
1633
+ label: "View Hugging Face dataset:",
1634
+ url: MANIFEST.trace_dataset,
1635
+ fallback: "Agent Traces dataset",
1636
+ };
1637
  }
1638
+ if (view === "workspace") {
1639
+ const bucketId = (MANIFEST.workspace || {}).bucket_id;
1640
+ const url =
1641
+ MANIFEST.workspace_bucket ||
1642
+ (bucketId ? `https://huggingface.co/buckets/${bucketId}` : "");
1643
+ if (url) {
1644
+ return {
1645
+ label: "View Hugging Face Bucket:",
1646
+ url,
1647
+ fallback: "Workspace Bucket",
1648
+ };
 
 
 
 
 
 
 
 
 
1649
  }
1650
+ }
1651
+ return null;
1652
+ }
1653
+
1654
+ function buildHubDestinationLink(view) {
1655
+ const destination = hubDestination(view);
1656
+ if (!destination || !destination.url.startsWith("https://huggingface.co/")) {
1657
+ return null;
1658
+ }
1659
+ const row = document.createElement("div");
1660
+ row.className = "hub-destination";
1661
+ const label = document.createElement("span");
1662
+ label.textContent = destination.label;
1663
+ const link = document.createElement("a");
1664
+ link.href = destination.url;
1665
+ link.target = "_blank";
1666
+ link.rel = "noopener noreferrer";
1667
+ link.textContent =
1668
+ destination.url
1669
+ .replace(/^https:\/\/huggingface\.co\/(?:datasets|buckets)\//, "")
1670
+ .replace(/\/$/, "") || destination.fallback;
1671
+ link.title = destination.url;
1672
+ const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1673
+ icon.setAttribute("viewBox", "0 0 24 24");
1674
+ icon.setAttribute("aria-hidden", "true");
1675
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
1676
+ path.setAttribute("d", "M14 5h5v5M19 5l-8 8M19 13v5a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5");
1677
+ icon.appendChild(path);
1678
+ link.appendChild(icon);
1679
+ row.appendChild(label);
1680
+ row.appendChild(link);
1681
+ return row;
1682
+ }
1683
+
1684
+ function buildAgentHint(view) {
1685
+ const target = readTarget(view);
1686
+ const command = `trackio logbook read${target ? ` ${target}` : ""}`;
1687
+ const tokens = MANIFEST[VIEW_TOKENS[view] || VIEW_TOKENS.code];
1688
+ const div = document.createElement("div");
1689
+ div.className = "agent-hint";
1690
+ const label = document.createElement("span");
1691
+ label.className = "agent-hint-label";
1692
+ label.textContent = "Read from the CLI:";
1693
+ const code = document.createElement("code");
1694
+ code.textContent = command;
1695
+ const copy = document.createElement("button");
1696
+ copy.className = "copy";
1697
+ copy.type = "button";
1698
+ copy.title = "Copy";
1699
+ copy.textContent = "⧉";
1700
+ copy.addEventListener("click", () => copyText(command, copy, "⧉"));
1701
+ const note = document.createElement("span");
1702
+ note.className = "agent-hint-note";
1703
+ note.textContent =
1704
+ "compact view for agents" + (tokens ? ` · ~${fmt(tokens)} tokens` : "");
1705
+ div.appendChild(label);
1706
+ div.appendChild(code);
1707
+ div.appendChild(copy);
1708
+ div.appendChild(note);
1709
+ return div;
1710
+ }
1711
+
1712
+ function routeState() {
1713
+ const raw = (location.hash || "").replace(/^#\/?/, "");
1714
+ if (!raw) return { view: "code", slug: MANIFEST.root.slug };
1715
+ const parts = raw.split("/");
1716
+ if (parts[0] !== "view") {
1717
+ const slug = findNode(MANIFEST.root, raw) ? raw : MANIFEST.root.slug;
1718
+ return { view: "code", slug };
1719
+ }
1720
+ if (parts[1] === "trace") {
1721
+ return { view: "trace", sessionId: parts.slice(2).join("/") || null };
1722
+ }
1723
+ if (parts[1] === "workspace") return { view: "workspace" };
1724
+ const candidate = parts.slice(2).join("/") || MANIFEST.root.slug;
1725
  return {
1726
+ view: "code",
1727
+ slug: findNode(MANIFEST.root, candidate) ? candidate : MANIFEST.root.slug,
 
 
 
 
1728
  };
1729
  }
1730
 
1731
+ function updateViewTabs(route = routeState()) {
1732
+ document.querySelectorAll("#view-tabs a").forEach((tab) => {
1733
+ const view = tab.dataset.view;
1734
+ tab.classList.toggle("active", view === route.view);
1735
+ tab.setAttribute("aria-current", view === route.view ? "page" : "false");
1736
+ if (view === "code") {
1737
+ const slug = route.view === "code" ? route.slug : MANIFEST.root.slug;
1738
+ tab.href = `#/view/code/${slug}`;
1739
+ } else if (view === "trace") {
1740
+ tab.href = "#/view/trace";
1741
+ }
1742
+ });
1743
  }
1744
 
1745
+ function setActiveView(route) {
1746
+ CURRENT_VIEW = route.view;
1747
+ document.body.dataset.view = route.view;
1748
+ updateViewTabs(route);
1749
+ renderLogbookHeader(route.view);
1750
+ renderSidebar(route);
1751
+ }
1752
+
1753
+ function formatDuration(ms) {
1754
+ if (ms == null || isNaN(ms)) return "—";
1755
+ const total = Math.max(0, Math.floor(ms / 1000));
1756
+ const hours = Math.floor(total / 3600);
1757
+ const minutes = Math.floor((total % 3600) / 60);
1758
+ const seconds = total % 60;
1759
+ if (hours) return `${hours}h ${minutes}m ${seconds}s`;
1760
+ if (minutes) return `${minutes}m ${seconds}s`;
1761
+ return `${seconds}s`;
1762
+ }
1763
+
1764
+ function formatDate(value) {
1765
+ if (!value) return "—";
1766
+ const date = new Date(value);
1767
+ if (isNaN(date.getTime())) return value;
1768
+ return date.toLocaleString([], {
1769
+ year: "numeric",
1770
+ month: "short",
1771
+ day: "numeric",
1772
+ hour: "numeric",
1773
+ minute: "2-digit",
1774
+ second: "2-digit",
1775
  });
1776
  }
1777
 
1778
+ function emptyView(title, text, command) {
1779
+ const empty = document.createElement("div");
1780
+ empty.className = "view-empty";
1781
+ const heading = document.createElement("h2");
1782
+ heading.textContent = title;
1783
+ const body = document.createElement("p");
1784
+ body.textContent = text;
1785
+ empty.appendChild(heading);
1786
+ empty.appendChild(body);
1787
+ if (command) {
1788
+ const code = document.createElement("code");
1789
+ code.textContent = command;
1790
+ empty.appendChild(code);
1791
+ }
1792
+ return empty;
1793
+ }
1794
+
1795
+ function traceEventLabel(event) {
1796
+ if (event.kind === "reasoning") return "Thought";
1797
+ if (event.kind === "tool_call") return event.tool_name || event.title || "Tool";
1798
+ if (event.kind === "tool_result") return "Tool output";
1799
+ return event.title || event.kind || "Event";
1800
+ }
1801
+
1802
+ function appendTraceResult(entry, result) {
1803
+ if (!entry || !result || !result.output) return;
1804
+ const card = entry.querySelector(".trace-card");
1805
+ if (!card) return;
1806
+ const details = document.createElement("details");
1807
+ details.className = "trace-output";
1808
+ const summary = document.createElement("summary");
1809
+ summary.textContent = result.status === "error" ? "Error output" : "Output";
1810
+ const output = document.createElement("pre");
1811
+ output.textContent = result.output;
1812
+ details.appendChild(summary);
1813
+ details.appendChild(output);
1814
+ card.appendChild(details);
1815
+ }
1816
+
1817
+ function traceEventCard(event, result) {
1818
+ const entry = document.createElement("div");
1819
+ entry.className = `trace-entry trace-${event.kind || "status"}`;
1820
+ entry.style.setProperty("--trace-depth", Math.min(Number(event.depth) || 0, 4));
1821
+
1822
+ const rail = document.createElement("div");
1823
+ rail.className = "trace-rail";
1824
+ const number = document.createElement("span");
1825
+ number.className = "trace-number";
1826
+ number.textContent = `#${event.sequence || ""}`;
1827
+ const dot = document.createElement("span");
1828
+ dot.className = "trace-dot";
1829
+ const elapsed = document.createElement("span");
1830
+ elapsed.className = "trace-elapsed";
1831
+ elapsed.textContent = formatDuration(event.elapsed_ms);
1832
+ rail.appendChild(number);
1833
+ rail.appendChild(dot);
1834
+ rail.appendChild(elapsed);
1835
+
1836
+ const card = document.createElement("article");
1837
+ card.className = "trace-card";
1838
+ const head = document.createElement("header");
1839
+ const kind = document.createElement("span");
1840
+ kind.className = "trace-kind";
1841
+ kind.textContent = traceEventLabel(event);
1842
+ head.appendChild(kind);
1843
+ if (event.turn) {
1844
+ const turn = document.createElement("span");
1845
+ turn.className = "trace-turn";
1846
+ turn.textContent = `turn ${event.turn}`;
1847
+ head.appendChild(turn);
1848
+ }
1849
+ card.appendChild(head);
1850
+
1851
+ const bodyText = event.text || event.input || event.output;
1852
+ if (bodyText) {
1853
+ const body = document.createElement(
1854
+ event.kind === "tool_call" || event.kind === "tool_result" ? "pre" : "div"
1855
+ );
1856
+ body.className = "trace-body";
1857
+ body.textContent = bodyText;
1858
+ card.appendChild(body);
1859
+ }
1860
+ if (event.status) {
1861
+ const status = document.createElement("span");
1862
+ status.className = `trace-status-badge trace-status-badge-${event.status}`;
1863
+ status.textContent = String(event.status).replace(/_/g, " ");
1864
+ head.appendChild(status);
1865
+ }
1866
+ entry.appendChild(rail);
1867
+ entry.appendChild(card);
1868
+ appendTraceResult(entry, result);
1869
+ return entry;
1870
  }
1871
 
1872
+ function traceSessionAnchor(id) {
1873
+ return "/view/trace/" + id;
1874
+ }
1875
+
1876
+ function buildTraceSession(session, index) {
1877
+ const sec = document.createElement("section");
1878
+ sec.className = "trace-session";
1879
+ sec.id = traceSessionAnchor(session.id);
1880
+ sec.dataset.sessionId = session.id;
1881
+
1882
+ const title = document.createElement("h2");
1883
+ title.className = "trace-session-title";
1884
+ title.textContent = session.title || session.id;
1885
+ sec.appendChild(title);
1886
+
1887
+ const meta = document.createElement("div");
1888
+ meta.className = "trace-meta";
1889
+ [
1890
+ ["Started", formatDate(index.started_at)],
1891
+ ["Ended", formatDate(index.ended_at)],
1892
+ ["Duration", formatDuration(index.duration_ms)],
1893
+ ["Events", String(index.event_count || 0)],
1894
+ ].forEach(([label, value]) => {
1895
+ const item = document.createElement("span");
1896
+ const strong = document.createElement("strong");
1897
+ strong.textContent = label;
1898
+ item.appendChild(strong);
1899
+ item.appendChild(document.createTextNode(` ${value}`));
1900
+ meta.appendChild(item);
1901
+ });
1902
+ if (index.model) {
1903
+ const model = document.createElement("span");
1904
+ const strong = document.createElement("strong");
1905
+ strong.textContent = "Model";
1906
+ model.appendChild(strong);
1907
+ model.appendChild(document.createTextNode(` ${index.model}`));
1908
+ meta.appendChild(model);
1909
+ }
1910
+ if (index.source_available === false) {
1911
+ const missing = document.createElement("span");
1912
+ missing.className = "trace-source-missing";
1913
+ missing.textContent = "Source file unavailable · showing last capture";
1914
+ meta.appendChild(missing);
1915
+ }
1916
+ sec.appendChild(meta);
1917
+
1918
+ const timeline = document.createElement("section");
1919
+ timeline.className = "trace-timeline";
1920
+ sec.appendChild(timeline);
1921
+
1922
+ const chunks = index.chunks || [];
1923
+ if (!chunks.length) {
1924
+ timeline.appendChild(
1925
+ emptyView("Empty trace", "No displayable events were found in this session.")
1926
+ );
1927
+ return sec;
1928
+ }
1929
+
1930
+ const controls = document.createElement("div");
1931
+ controls.className = "trace-load-controls";
1932
+ const progress = document.createElement("span");
1933
+ progress.className = "trace-load-progress";
1934
+ const loadMore = document.createElement("button");
1935
+ loadMore.type = "button";
1936
+ loadMore.className = "trace-load-more";
1937
+ controls.appendChild(progress);
1938
+ controls.appendChild(loadMore);
1939
+ sec.appendChild(controls);
1940
+
1941
+ let nextChunk = 0;
1942
+ let loadedEvents = 0;
1943
+ let loading = false;
1944
+ const pendingCalls = new Map();
1945
+
1946
+ function updateLoadControls() {
1947
+ const total = Number(index.event_count) || chunks.reduce(
1948
+ (sum, chunk) => sum + (Number(chunk.count) || 0),
1949
+ 0
1950
+ );
1951
+ progress.textContent = `${Math.min(loadedEvents, total)} of ${total} events loaded`;
1952
+ if (nextChunk >= chunks.length) {
1953
+ loadMore.textContent = "All events loaded";
1954
+ loadMore.disabled = true;
1955
+ return;
1956
+ }
1957
+ const count = Number(chunks[nextChunk].count) || "next";
1958
+ loadMore.textContent = `Load ${count} more events`;
1959
+ loadMore.disabled = false;
1960
+ }
1961
+
1962
+ async function loadNextTraceChunk() {
1963
+ if (loading || nextChunk >= chunks.length) return;
1964
+ loading = true;
1965
+ loadMore.disabled = true;
1966
+ loadMore.textContent = "Loading…";
1967
+ const descriptor = chunks[nextChunk];
1968
+ try {
1969
+ // Event chunks can be large. Do not retain the parsed JSON in DATA_CACHE;
1970
+ // the rendered DOM is the only long-lived copy.
1971
+ const chunk = await fetchData(descriptor.file, false);
1972
+ const events = chunk.events || [];
1973
+ events.forEach((event) => {
1974
+ if (
1975
+ event.kind === "tool_result" &&
1976
+ event.call_id &&
1977
+ pendingCalls.has(event.call_id)
1978
+ ) {
1979
+ appendTraceResult(pendingCalls.get(event.call_id), event);
1980
+ pendingCalls.delete(event.call_id);
1981
  return;
1982
  }
1983
+ const entry = traceEventCard(event);
1984
+ timeline.appendChild(entry);
1985
+ if (event.kind === "tool_call" && event.call_id) {
1986
+ pendingCalls.set(event.call_id, entry);
1987
+ }
1988
  });
1989
+ loadedEvents += events.length;
1990
+ nextChunk += 1;
1991
+ sec.dataset.loadedChunks = String(nextChunk);
1992
+ updateLoadControls();
1993
+ } catch (error) {
1994
+ progress.textContent = "Could not load the next trace segment.";
1995
+ loadMore.textContent = "Retry";
1996
+ loadMore.disabled = false;
1997
+ } finally {
1998
+ loading = false;
 
 
 
1999
  }
2000
+ }
2001
+
2002
+ sec.dataset.loadedChunks = "0";
2003
+ sec.loadNextTraceChunk = loadNextTraceChunk;
2004
+ loadMore.addEventListener("click", loadNextTraceChunk);
2005
+ updateLoadControls();
2006
+ return sec;
2007
+ }
2008
+
2009
+ function ensureTraceSessionLoaded(sessionId) {
2010
+ const target = document.getElementById(traceSessionAnchor(sessionId));
2011
+ if (
2012
+ target &&
2013
+ target.dataset.loadedChunks === "0" &&
2014
+ typeof target.loadNextTraceChunk === "function"
2015
+ ) {
2016
+ return target.loadNextTraceChunk();
2017
+ }
2018
+ return Promise.resolve();
2019
  }
2020
 
2021
+ function scrollToTraceSession(sessionId) {
2022
+ if (!sessionId) {
2023
+ window.scrollTo({ top: 0, behavior: "auto" });
2024
+ return;
2025
+ }
2026
+ const target = document.getElementById(traceSessionAnchor(sessionId));
2027
+ if (target) target.scrollIntoView({ behavior: "auto" });
2028
+ else window.scrollTo({ top: 0, behavior: "auto" });
2029
+ }
2030
 
2031
+ // A published static Space may store only a reference to a private (or
2032
+ // public) repository instead of embedding trace/workspace content. These
2033
+ // helpers render that reference: link-only for private/inaccessible repos,
2034
+ // and a probe-then-render path for public ones.
2035
+ function repoRefCard(ref, opts) {
2036
+ const wrap = document.createElement("div");
2037
+ wrap.className = "view-empty repo-ref-card";
2038
+ const h = document.createElement("h2");
2039
+ h.textContent = opts.title;
2040
+ wrap.appendChild(h);
2041
+ const p = document.createElement("p");
2042
+ p.textContent = opts.message;
2043
+ wrap.appendChild(p);
2044
+ if (ref && ref.repo_url) {
2045
+ const a = document.createElement("a");
2046
+ a.className = "repo-ref-link";
2047
+ a.href = ref.repo_url;
2048
+ a.target = "_blank";
2049
+ a.rel = "noopener noreferrer";
2050
+ a.textContent = "Open on the Hub ↗";
2051
+ wrap.appendChild(a);
2052
+ }
2053
+ return wrap;
2054
+ }
2055
+
2056
+ async function probeRepoAccessible(ref) {
2057
+ if (!ref || !ref.repo_id) return false;
2058
+ let url = "";
2059
+ if (ref.repo_type === "dataset") {
2060
+ url = "https://huggingface.co/api/datasets/" + ref.repo_id;
2061
+ } else if (ref.repo_type === "bucket") {
2062
+ url = "https://huggingface.co/api/buckets/" + ref.repo_id;
2063
+ }
2064
+ if (!url) return ref.private === false;
2065
+ try {
2066
+ const response = await fetch(url, { cache: "no-store" });
2067
+ if (!response.ok) return false;
2068
+ const metadata = await response.json();
2069
+ return metadata.private !== true;
2070
+ } catch (error) {
2071
+ return false;
2072
+ }
2073
+ }
2074
+
2075
+ async function renderRepoReference(ref, kind, page, renderId) {
2076
+ const isTraces = kind === "traces";
2077
+ const noun = isTraces ? "agent traces" : "workspace files";
2078
+ const linkOnly = () =>
2079
+ repoRefCard(ref, {
2080
+ title: isTraces ? "Agent traces" : "Workspace",
2081
+ message:
2082
+ `These ${noun} live in a private repository. ` +
2083
+ "Open it on the Hub to view them.",
2084
+ });
2085
+ const accessible = await probeRepoAccessible(ref);
2086
+ if (renderId !== RENDER_SEQUENCE) return;
2087
+ if (!accessible) {
2088
+ page.appendChild(linkOnly());
2089
+ return;
2090
+ }
2091
+ page.appendChild(
2092
+ repoRefCard(ref, {
2093
+ title: isTraces ? "Agent traces" : "Workspace",
2094
+ message:
2095
+ `These ${noun} are published to a public repository on the Hub.`,
2096
+ })
2097
  );
2098
+ }
2099
+
2100
+ async function renderTrace(route, renderId) {
2101
+ const page = document.getElementById("page");
2102
+ page.innerHTML = "";
2103
+ page.className = "trace-page";
2104
+ const sessions = MANIFEST.traces || [];
2105
+ if (!sessions.length) {
2106
+ updateViewTabs({ view: "trace" });
2107
+ if (MANIFEST.traces_ref && MANIFEST.traces_ref.repo_url) {
2108
+ await renderRepoReference(MANIFEST.traces_ref, "traces", page, renderId);
2109
+ return;
2110
  }
2111
+ page.appendChild(
2112
+ emptyView(
2113
+ "No agent sessions attached yet",
2114
+ "Attach the active session once and Trackio will keep its trace refreshed here while you work. The session stays local until you explicitly publish it.",
2115
+ "trackio logbook attach trace <session.jsonl>"
2116
+ )
2117
+ );
2118
+ return;
2119
+ }
2120
+ updateViewTabs({ view: "trace" });
2121
+
2122
+ const loading = document.createElement("div");
2123
+ loading.className = "view-loading";
2124
+ loading.textContent = "Loading traces…";
2125
+ page.appendChild(loading);
2126
+ let loaded;
2127
+ try {
2128
+ loaded = await Promise.all(
2129
+ sessions.map(async (session) => {
2130
+ const index = await fetchData(session.index_file);
2131
+ return { session, index };
 
2132
  })
2133
+ );
2134
+ } catch (error) {
2135
+ if (renderId !== RENDER_SEQUENCE) return;
2136
+ page.innerHTML = "";
2137
+ page.appendChild(
2138
+ emptyView("Trace unavailable", "The normalized traces could not be loaded.")
2139
+ );
2140
+ return;
2141
+ }
2142
+ if (renderId !== RENDER_SEQUENCE) return;
2143
+ page.innerHTML = "";
2144
+
2145
+ const shell = document.createElement("div");
2146
+ shell.className = "trace-shell";
2147
+ loaded.forEach(({ session, index }) => {
2148
+ shell.appendChild(buildTraceSession(session, index));
2149
  });
2150
+ page.appendChild(shell);
2151
+ const activeSessionId = route.sessionId || sessions[0].id;
2152
+ await ensureTraceSessionLoaded(activeSessionId);
2153
+ if (renderId !== RENDER_SEQUENCE) return;
2154
+ scrollToTraceSession(activeSessionId);
2155
+ }
2156
+
2157
+ function svgIcon(kind) {
2158
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
2159
+ svg.setAttribute("viewBox", "0 0 24 24");
2160
+ svg.setAttribute("aria-hidden", "true");
2161
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
2162
+ path.setAttribute(
2163
+ "d",
2164
+ kind === "folder"
2165
+ ? "M3.5 6.5h6l2 2h9v9a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"
2166
+ : kind === "download"
2167
+ ? "M12 3v12m0 0 4-4m-4 4-4-4M5 20h14"
2168
+ : "M6 3.5h8l4 4V20H6zM14 3.5V8h4"
2169
+ );
2170
+ svg.appendChild(path);
2171
+ return svg;
2172
+ }
2173
+
2174
+ function workspaceTree(files) {
2175
+ const root = { directories: new Map(), files: [] };
2176
+ files.forEach((file) => {
2177
+ const parts = file.path.split("/");
2178
+ let cursor = root;
2179
+ parts.slice(0, -1).forEach((name) => {
2180
+ if (!cursor.directories.has(name)) {
2181
+ cursor.directories.set(name, { directories: new Map(), files: [] });
2182
+ }
2183
+ cursor = cursor.directories.get(name);
2184
+ });
2185
+ cursor.files.push(file);
2186
+ });
2187
+ return root;
2188
  }
2189
 
2190
+ function workspaceFileRow(file) {
2191
+ const row = document.createElement("div");
2192
+ row.className = "workspace-file";
2193
+ const name = document.createElement("div");
2194
+ name.className = "workspace-file-name";
2195
+ name.appendChild(svgIcon("file"));
 
 
 
 
 
 
 
 
2196
  const label = document.createElement("span");
2197
+ label.textContent = file.name;
2198
+ label.title = file.path;
2199
+ name.appendChild(label);
2200
+ const type = document.createElement("span");
2201
+ type.className = "workspace-file-type";
2202
+ type.textContent = file.type || "file";
2203
+ const size = document.createElement("span");
2204
+ size.className = "workspace-file-size";
2205
+ size.textContent = fmtBytes(file.size) || "";
2206
+ const modified = document.createElement("time");
2207
+ modified.className = "workspace-file-time";
2208
+ modified.dateTime = file.modified_at || "";
2209
+ modified.textContent = formatDate(file.modified_at);
2210
+ row.appendChild(name);
2211
+ row.appendChild(type);
2212
+ row.appendChild(size);
2213
+ row.appendChild(modified);
2214
+ const url =
2215
+ isLocalPreview() && file.local_url
2216
+ ? file.local_url
2217
+ : file.download_url || file.bucket_url;
2218
+ if (url) {
2219
+ const download = document.createElement("a");
2220
+ download.className = "workspace-download";
2221
+ download.href = url;
2222
+ download.title = "Download";
2223
+ download.setAttribute("aria-label", `Download ${file.name}`);
2224
+ if (isLocalPreview() && file.local_url) download.download = file.name;
2225
+ download.appendChild(svgIcon("download"));
2226
+ row.appendChild(download);
2227
+ } else {
2228
+ const pending = document.createElement("span");
2229
+ pending.className = "workspace-unpublished";
2230
+ pending.textContent = "Local";
2231
+ row.appendChild(pending);
2232
+ }
2233
+ return row;
2234
+ }
2235
+
2236
+ function renderWorkspaceNode(node, container) {
2237
+ Array.from(node.directories.entries())
2238
+ .sort(([a], [b]) => a.localeCompare(b))
2239
+ .forEach(([name, child]) => {
2240
+ const details = document.createElement("details");
2241
+ details.className = "workspace-folder";
2242
+ details.open = true;
2243
+ const summary = document.createElement("summary");
2244
+ summary.appendChild(svgIcon("folder"));
2245
+ const label = document.createElement("span");
2246
+ label.textContent = name;
2247
+ summary.appendChild(label);
2248
+ details.appendChild(summary);
2249
+ const children = document.createElement("div");
2250
+ children.className = "workspace-folder-children";
2251
+ renderWorkspaceNode(child, children);
2252
+ details.appendChild(children);
2253
+ container.appendChild(details);
2254
+ });
2255
+ node.files
2256
+ .sort((a, b) => a.name.localeCompare(b.name))
2257
+ .forEach((file) => container.appendChild(workspaceFileRow(file)));
2258
+ }
2259
+
2260
+ const WORKSPACE_MODE_KEY = "trackio-logbook:workspace-mode";
2261
+
2262
+ function getWorkspaceMode() {
2263
+ try {
2264
+ return localStorage.getItem(WORKSPACE_MODE_KEY) === "type" ? "type" : "tree";
2265
+ } catch (error) {
2266
+ return "tree";
2267
+ }
2268
+ }
2269
+
2270
+ function setWorkspaceMode(mode) {
2271
+ try {
2272
+ localStorage.setItem(WORKSPACE_MODE_KEY, mode);
2273
+ } catch (error) {
2274
+ /* ignore storage failures (private mode, etc.) */
2275
+ }
2276
+ }
2277
+
2278
+ function fileGroupKey(file) {
2279
+ if (file.type) return file.type;
2280
+ const name = file.name || file.path || "";
2281
+ const dot = name.lastIndexOf(".");
2282
+ if (dot > 0 && dot < name.length - 1) return name.slice(dot + 1).toLowerCase();
2283
+ return "other";
2284
+ }
2285
+
2286
+ function renderWorkspaceByType(files, container) {
2287
+ const groups = new Map();
2288
+ files.forEach((file) => {
2289
+ const key = fileGroupKey(file);
2290
+ if (!groups.has(key)) groups.set(key, []);
2291
+ groups.get(key).push(file);
2292
+ });
2293
+ Array.from(groups.keys())
2294
+ .sort((a, b) => a.localeCompare(b))
2295
+ .forEach((key) => {
2296
+ const items = groups
2297
+ .get(key)
2298
+ .sort((a, b) => a.name.localeCompare(b.name));
2299
+ const section = document.createElement("div");
2300
+ section.className = "workspace-group";
2301
+ const heading = document.createElement("h3");
2302
+ heading.className = "workspace-group-head";
2303
+ const label = document.createElement("span");
2304
+ label.textContent = key;
2305
+ const count = document.createElement("span");
2306
+ count.className = "workspace-group-count";
2307
+ count.textContent = String(items.length);
2308
+ heading.appendChild(label);
2309
+ heading.appendChild(count);
2310
+ section.appendChild(heading);
2311
+ items.forEach((file) => section.appendChild(workspaceFileRow(file)));
2312
+ container.appendChild(section);
2313
+ });
2314
+ }
2315
+
2316
+ function buildWorkspaceToggle(current, onChange) {
2317
+ const toggle = document.createElement("div");
2318
+ toggle.className = "workspace-toggle";
2319
+ toggle.setAttribute("role", "group");
2320
+ toggle.setAttribute("aria-label", "Workspace layout");
2321
+ const buttons = [];
2322
+ [
2323
+ ["tree", "Tree"],
2324
+ ["type", "By type"],
2325
+ ].forEach(([mode, text]) => {
2326
+ const btn = document.createElement("button");
2327
+ btn.type = "button";
2328
+ btn.className = "workspace-toggle-btn";
2329
+ btn.textContent = text;
2330
+ const setActive = (active) => {
2331
+ btn.classList.toggle("is-active", active);
2332
+ btn.setAttribute("aria-pressed", active ? "true" : "false");
2333
+ };
2334
+ setActive(mode === current);
2335
+ btn.addEventListener("click", () => {
2336
+ buttons.forEach((entry) => entry.setActive(entry.mode === mode));
2337
+ onChange(mode);
2338
+ });
2339
+ buttons.push({ mode, setActive });
2340
+ toggle.appendChild(btn);
2341
+ });
2342
+ return toggle;
2343
+ }
2344
+
2345
+ const HF_LOGO_DATA_URI = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NSIgaGVpZ2h0PSI4OCIgZmlsbD0ibm9uZSI+Cgk8cGF0aCBmaWxsPSIjRkZEMjFFIiBkPSJNNDcuMjEgNzYuNWEzNC43NSAzNC43NSAwIDEgMCAwLTY5LjUgMzQuNzUgMzQuNzUgMCAwIDAgMCA2OS41WiIgLz4KCTxwYXRoCgkJZmlsbD0iI0ZGOUQwQiIKCQlkPSJNODEuOTYgNDEuNzVhMzQuNzUgMzQuNzUgMCAxIDAtNjkuNSAwIDM0Ljc1IDM0Ljc1IDAgMCAwIDY5LjUgMFptLTczLjUgMGEzOC43NSAzOC43NSAwIDEgMSA3Ny41IDAgMzguNzUgMzguNzUgMCAwIDEtNzcuNSAwWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiMzQTNCNDUiCgkJZD0iTTU4LjUgMzIuM2MxLjI4LjQ0IDEuNzggMy4wNiAzLjA3IDIuMzhhNSA1IDAgMSAwLTYuNzYtMi4wN2MuNjEgMS4xNSAyLjU1LS43MiAzLjctLjMyWk0zNC45NSAzMi4zYy0xLjI4LjQ0LTEuNzkgMy4wNi0zLjA3IDIuMzhhNSA1IDAgMSAxIDYuNzYtMi4wN2MtLjYxIDEuMTUtMi41Ni0uNzItMy43LS4zMloiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkYzMjNEIgoJCWQ9Ik00Ni45NiA1Ni4yOWM5LjgzIDAgMTMtOC43NiAxMy0xMy4yNiAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzYtMi4zMyAxLjE1LTUuNDYgMi43NC04LjkgMi43NC03LjE5IDAtMTMtNi44OC0xMy0yLjM4czMuMTYgMTMuMjYgMTMgMTMuMjZaIgoJLz4KCTxwYXRoCgkJZmlsbD0iIzNBM0I0NSIKCQlmaWxsLXJ1bGU9ImV2ZW5vZGQiCgkJZD0iTTM5LjQzIDU0YTguNyA4LjcgMCAwIDEgNS4zLTQuNDljLjQtLjEyLjgxLjU3IDEuMjQgMS4yOC40LjY4LjgyIDEuMzcgMS4yNCAxLjM3LjQ1IDAgLjktLjY4IDEuMzMtMS4zNS40NS0uNy44OS0xLjM4IDEuMzItMS4yNWE4LjYxIDguNjEgMCAwIDEgNSA0LjE3YzMuNzMtMi45NCA1LjEtNy43NCA1LjEtMTAuNyAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzZsLS4xNC4wN2MtMi4zMSAxLjE1LTUuMzkgMi42Ny04Ljc3IDIuNjdzLTYuNDUtMS41Mi04Ljc3LTIuNjdjLTIuNi0xLjI5LTQuMjMtMi4xLTQuMjMuMjkgMCAzLjA1IDEuNDYgOC4wNiA1LjQ3IDEwLjk3WiIKCQljbGlwLXJ1bGU9ImV2ZW5vZGQiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkY5RDBCIgoJCWQ9Ik03MC43MSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0yNC4yMSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0xNy41MiA0OGMtMS42MiAwLTMuMDYuNjYtNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMC0xLjMzIDMuNzYgNy4xIDcuMSAwIDAgMC0xLjk0LS4zYy0xLjU1IDAtMi45NS41OS0zLjk0IDEuNjZhNS44IDUuOCAwIDAgMC0uOCA3IDUuMyA1LjMgMCAwIDAtMS43OSAyLjgyYy0uMjQuOS0uNDggMi44LjggNC43NGE1LjIyIDUuMjIgMCAwIDAtLjM3IDUuMDJjMS4wMiAyLjMyIDMuNTcgNC4xNCA4LjUyIDYuMSAzLjA3IDEuMjIgNS44OSAyIDUuOTEgMi4wMWE0NC4zMyA0NC4zMyAwIDAgMCAxMC45MyAxLjZjNS44NiAwIDEwLjA1LTEuOCAxMi40Ni01LjM0IDMuODgtNS42OSAzLjMzLTEwLjktMS43LTE1LjkyLTIuNzctMi43OC00LjYyLTYuODctNS03Ljc3LS43OC0yLjY2LTIuODQtNS42Mi02LjI1LTUuNjJhNS43IDUuNyAwIDAgMC00LjYgMi40NmMtMS0xLjI2LTEuOTgtMi4yNS0yLjg2LTIuODJBNy40IDcuNCAwIDAgMCAxNy41MiA0OFptMCA0Yy41MSAwIDEuMTQuMjIgMS44Mi42NSAyLjE0IDEuMzYgNi4yNSA4LjQzIDcuNzYgMTEuMTguNS45MiAxLjM3IDEuMzEgMi4xNCAxLjMxIDEuNTUgMCAyLjc1LTEuNTMuMTUtMy40OC0zLjkyLTIuOTMtMi41NS03LjcyLS42OC04LjAxLjA4LS4wMi4xNy0uMDIuMjQtLjAyIDEuNyAwIDIuNDUgMi45MyAyLjQ1IDIuOTNzMi4yIDUuNTIgNS45OCA5LjNjMy43NyAzLjc3IDMuOTcgNi44IDEuMjIgMTAuODMtMS44OCAyLjc1LTUuNDcgMy41OC05LjE2IDMuNTgtMy44MSAwLTcuNzMtLjktOS45Mi0xLjQ2LS4xMS0uMDMtMTMuNDUtMy44LTExLjc2LTcgLjI4LS41NC43NS0uNzYgMS4zNC0uNzYgMi4zOCAwIDYuNyAzLjU0IDguNTcgMy41NC40MSAwIC43LS4xNy44My0uNi43OS0yLjg1LTEyLjA2LTQuMDUtMTAuOTgtOC4xNy4yLS43My43MS0xLjAyIDEuNDQtMS4wMiAzLjE0IDAgMTAuMiA1LjUzIDExLjY4IDUuNTMuMTEgMCAuMi0uMDMuMjQtLjEuNzQtMS4yLjMzLTIuMDQtNC45LTUuMi01LjIxLTMuMTYtOC44OC01LjA2LTYuOC03LjMzLjI0LS4yNi41OC0uMzggMS0uMzggMy4xNyAwIDEwLjY2IDYuODIgMTAuNjYgNi44MnMyLjAyIDIuMSAzLjI1IDIuMWMuMjggMCAuNTItLjEuNjgtLjM4Ljg2LTEuNDYtOC4wNi04LjIyLTguNTYtMTEuMDEtLjM0LTEuOS4yNC0yLjg1IDEuMzEtMi44NVoiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkZEMjFFIgoJCWQ9Ik0zOC42IDc2LjY5YzIuNzUtNC4wNCAyLjU1LTcuMDctMS4yMi0xMC44NC0zLjc4LTMuNzctNS45OC05LjMtNS45OC05LjNzLS44Mi0zLjItMi42OS0yLjljLTEuODcuMy0zLjI0IDUuMDguNjggOC4wMSAzLjkxIDIuOTMtLjc4IDQuOTItMi4yOSAyLjE3LTEuNS0yLjc1LTUuNjItOS44Mi03Ljc2LTExLjE4LTIuMTMtMS4zNS0zLjYzLS42LTMuMTMgMi4yLjUgMi43OSA5LjQzIDkuNTUgOC41NiAxMS0uODcgMS40Ny0zLjkzLTEuNzEtMy45My0xLjcxcy05LjU3LTguNzEtMTEuNjYtNi40NGMtMi4wOCAyLjI3IDEuNTkgNC4xNyA2LjggNy4zMyA1LjIzIDMuMTYgNS42NCA0IDQuOSA1LjItLjc1IDEuMi0xMi4yOC04LjUzLTEzLjM2LTQuNC0xLjA4IDQuMTEgMTEuNzcgNS4zIDEwLjk4IDguMTUtLjggMi44NS05LjA2LTUuMzgtMTAuNzQtMi4xOC0xLjcgMy4yMSAxMS42NSA2Ljk4IDExLjc2IDcuMDEgNC4zIDEuMTIgMTUuMjUgMy40OSAxOS4wOC0yLjEyWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiNGRjlEMEIiCgkJZD0iTTc3LjQgNDhjMS42MiAwIDMuMDcuNjYgNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMSAxLjMzIDMuNzYgNy4xIDcuMSAwIDAgMSAxLjk1LS4zYzEuNTUgMCAyLjk1LjU5IDMuOTQgMS42NmE1LjggNS44IDAgMCAxIC44IDcgNS4zIDUuMyAwIDAgMSAxLjc4IDIuODJjLjI0LjkuNDggMi44LS44IDQuNzRhNS4yMiA1LjIyIDAgMCAxIC4zNyA1LjAyYy0xLjAyIDIuMzItMy41NyA0LjE0LTguNTEgNi4xLTMuMDggMS4yMi01LjkgMi01LjkyIDIuMDFhNDQuMzMgNDQuMzMgMCAwIDEtMTAuOTMgMS42Yy01Ljg2IDAtMTAuMDUtMS44LTEyLjQ2LTUuMzQtMy44OC01LjY5LTMuMzMtMTAuOSAxLjctMTUuOTIgMi43OC0yLjc4IDQuNjMtNi44NyA1LjAxLTcuNzcuNzgtMi42NiAyLjgzLTUuNjIgNi4yNC01LjYyYTUuNyA1LjcgMCAwIDEgNC42IDIuNDZjMS0xLjI2IDEuOTgtMi4yNSAyLjg3LTIuODJBNy40IDcuNCAwIDAgMSA3Ny40IDQ4Wm0wIDRjLS41MSAwLTEuMTMuMjItMS44Mi42NS0yLjEzIDEuMzYtNi4yNSA4LjQzLTcuNzYgMTEuMThhMi40MyAyLjQzIDAgMCAxLTIuMTQgMS4zMWMtMS41NCAwLTIuNzUtMS41My0uMTQtMy40OCAzLjkxLTIuOTMgMi41NC03LjcyLjY3LTguMDFhMS41NCAxLjU0IDAgMCAwLS4yNC0uMDJjLTEuNyAwLTIuNDUgMi45My0yLjQ1IDIuOTNzLTIuMiA1LjUyLTUuOTcgOS4zYy0zLjc4IDMuNzctMy45OCA2LjgtMS4yMiAxMC44MyAxLjg3IDIuNzUgNS40NyAzLjU4IDkuMTUgMy41OCAzLjgyIDAgNy43My0uOSA5LjkzLTEuNDYuMS0uMDMgMTMuNDUtMy44IDExLjc2LTctLjI5LS41NC0uNzUtLjc2LTEuMzQtLjc2LTIuMzggMC02LjcxIDMuNTQtOC41NyAzLjU0LS40MiAwLS43MS0uMTctLjgzLS42LS44LTIuODUgMTIuMDUtNC4wNSAxMC45Ny04LjE3LS4xOS0uNzMtLjctMS4wMi0xLjQ0LTEuMDItMy4xNCAwLTEwLjIgNS41My0xMS42OCA1LjUzLS4xIDAtLjE5LS4wMy0uMjMtLjEtLjc0LTEuMi0uMzQtMi4wNCA0Ljg4LTUuMiA1LjIzLTMuMTYgOC45LTUuMDYgNi44LTcuMzMtLjIzLS4yNi0uNTctLjM4LS45OC0uMzgtMy4xOCAwLTEwLjY3IDYuODItMTAuNjcgNi44MnMtMi4wMiAyLjEtMy4yNCAyLjFhLjc0Ljc0IDAgMCAxLS42OC0uMzhjLS44Ny0xLjQ2IDguMDUtOC4yMiA4LjU1LTExLjAxLjM0LTEuOS0uMjQtMi44NS0xLjMxLTIuODVaIgoJLz4KCTxwYXRoCgkJZmlsbD0iI0ZGRDIxRSIKCQlkPSJNNTYuMzMgNzYuNjljLTIuNzUtNC4wNC0yLjU2LTcuMDcgMS4yMi0xMC44NCAzLjc3LTMuNzcgNS45Ny05LjMgNS45Ny05LjNzLjgyLTMuMiAyLjctMi45YzEuODYuMyAzLjIzIDUuMDgtLjY4IDguMDEtMy45MiAyLjkzLjc4IDQuOTIgMi4yOCAyLjE3IDEuNTEtMi43NSA1LjYzLTkuODIgNy43Ni0xMS4xOCAyLjEzLTEuMzUgMy42NC0uNiAzLjEzIDIuMi0uNSAyLjc5LTkuNDIgOS41NS04LjU1IDExIC44NiAxLjQ3IDMuOTItMS43MSAzLjkyLTEuNzFzOS41OC04LjcxIDExLjY2LTYuNDRjMi4wOCAyLjI3LTEuNTggNC4xNy02LjggNy4zMy01LjIzIDMuMTYtNS42MyA0LTQuOSA1LjIuNzUgMS4yIDEyLjI4LTguNTMgMTMuMzYtNC40IDEuMDggNC4xMS0xMS43NiA1LjMtMTAuOTcgOC4xNS44IDIuODUgOS4wNS01LjM4IDEwLjc0LTIuMTggMS42OSAzLjIxLTExLjY1IDYuOTgtMTEuNzYgNy4wMS00LjMxIDEuMTItMTUuMjYgMy40OS0xOS4wOC0yLjEyWiIKCS8+Cjwvc3ZnPgo=";
2346
+
2347
+ function hubGroupId(type) {
2348
+ return "ws-hub-" + String(type).toLowerCase().replace(/[^a-z0-9]+/g, "-");
2349
+ }
2350
+
2351
+ const HUB_REF_GROUP_ORDER = [
2352
+ "Jobs",
2353
+ "Datasets",
2354
+ "Models",
2355
+ "Spaces",
2356
+ "Buckets",
2357
+ "Collections",
2358
+ "Papers",
2359
+ ];
2360
+
2361
+ function hubRefFromRepoRef(ref) {
2362
+ if (!ref || !ref.repo_id || !ref.repo_url) return null;
2363
+ if (ref.repo_type === "dataset") {
2364
+ return { url: ref.repo_url, type: "Datasets", label: ref.repo_id };
2365
+ }
2366
+ if (ref.repo_type === "bucket") {
2367
+ return { url: ref.repo_url, type: "Buckets", label: ref.repo_id };
2368
+ }
2369
+ return null;
2370
+ }
2371
+
2372
+ async function publicAssociatedHubRefs() {
2373
+ const refs = [MANIFEST.traces_ref, MANIFEST.workspace_ref].filter(Boolean);
2374
+ const publicStates = await Promise.all(refs.map(probeRepoAccessible));
2375
+ return refs
2376
+ .filter((ref, index) => publicStates[index])
2377
+ .map(hubRefFromRepoRef)
2378
+ .filter(Boolean);
2379
+ }
2380
+
2381
+ function mergeHubRefs(...groups) {
2382
+ const merged = [];
2383
+ const seen = new Set();
2384
+ groups.flat().forEach((ref) => {
2385
+ if (!validHubRef(ref)) return;
2386
+ const key = `${ref.type || "Other"}:${ref.label || ref.url}`;
2387
+ if (seen.has(key)) return;
2388
+ seen.add(key);
2389
+ merged.push(ref);
2390
+ });
2391
+ return merged;
2392
+ }
2393
+
2394
+ function validHubRef(ref) {
2395
+ if (!ref || !ref.url) return false;
2396
+ if (classifyResource(ref.url)) return true;
2397
+ const match = ref.url.match(/huggingface\.co\/collections\/([^/?#]+\/[^/?#]+)/);
2398
+ return Boolean(match && validHfRepoId(match[1].split("/")));
2399
+ }
2400
+
2401
+ function renderHubRefs(refs) {
2402
+ const validRefs = Array.isArray(refs) ? refs.filter(validHubRef) : [];
2403
+ if (!validRefs.length) return null;
2404
+ const section = document.createElement("section");
2405
+ section.className = "workspace-hub";
2406
+ const heading = document.createElement("h2");
2407
+ heading.className = "workspace-hub-title";
2408
+ const hubLogo = document.createElement("img");
2409
+ hubLogo.className = "workspace-hub-logo";
2410
+ hubLogo.src = HF_LOGO_DATA_URI;
2411
+ hubLogo.alt = "";
2412
+ hubLogo.setAttribute("aria-hidden", "true");
2413
+ heading.appendChild(hubLogo);
2414
+ heading.appendChild(document.createTextNode("Hugging Face artifacts"));
2415
+ section.appendChild(heading);
2416
+ const byType = new Map();
2417
+ validRefs.forEach((ref) => {
2418
+ const type = ref.type || "Other";
2419
+ if (!byType.has(type)) byType.set(type, []);
2420
+ byType.get(type).push(ref);
2421
+ });
2422
+ const order = [
2423
+ ...HUB_REF_GROUP_ORDER,
2424
+ ...Array.from(byType.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
2425
+ ];
2426
+ order.forEach((type) => {
2427
+ const items = byType.get(type);
2428
+ if (!items || !items.length) return;
2429
+ const group = document.createElement("div");
2430
+ group.className = "workspace-hub-group";
2431
+ group.id = hubGroupId(type);
2432
+ const gh = document.createElement("h3");
2433
+ gh.className = "workspace-hub-group-head";
2434
+ const label = document.createElement("span");
2435
+ label.textContent = type;
2436
+ const count = document.createElement("span");
2437
+ count.className = "workspace-hub-count";
2438
+ count.textContent = String(items.length);
2439
+ gh.appendChild(label);
2440
+ gh.appendChild(count);
2441
+ group.appendChild(gh);
2442
+ const list = document.createElement("div");
2443
+ list.className = "workspace-hub-list";
2444
+ items.forEach((ref) => {
2445
+ const link = document.createElement("a");
2446
+ link.className = "workspace-hub-link";
2447
+ link.href = ref.url;
2448
+ link.target = "_blank";
2449
+ link.rel = "noopener noreferrer";
2450
+ link.textContent = ref.label || ref.url;
2451
+ link.title = ref.url;
2452
+ list.appendChild(link);
2453
+ });
2454
+ group.appendChild(list);
2455
+ section.appendChild(group);
2456
+ });
2457
+ return section;
2458
+ }
2459
+
2460
+ function workspaceSidebarEntries(files, hubRefs) {
2461
+ const entries = [];
2462
+ if (files && files.length) entries.push({ id: "ws-files", label: "Files" });
2463
+ const counts = new Map();
2464
+ (Array.isArray(hubRefs) ? hubRefs : []).filter(validHubRef).forEach((ref) => {
2465
+ const type = ref.type || "Other";
2466
+ counts.set(type, (counts.get(type) || 0) + 1);
2467
+ });
2468
+ const order = [
2469
+ ...HUB_REF_GROUP_ORDER,
2470
+ ...Array.from(counts.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
2471
+ ];
2472
+ order.forEach((type) => {
2473
+ if (counts.get(type)) entries.push({ id: hubGroupId(type), label: type });
2474
+ });
2475
+ return entries;
2476
+ }
2477
+
2478
+ function buildWorkspaceSidebar(entries) {
2479
+ const tree = document.getElementById("tree");
2480
+ tree.innerHTML = "";
2481
+ if (!entries || !entries.length) return;
2482
+ const label = document.createElement("div");
2483
+ label.className = "tree-label";
2484
+ label.textContent = "Sections";
2485
+ tree.appendChild(label);
2486
+ entries.forEach((entry) => {
2487
+ const a = document.createElement("a");
2488
+ a.href = "#/view/workspace";
2489
+ a.className = "depth-0";
2490
+ a.dataset.section = entry.id;
2491
+ const mark = document.createElement("span");
2492
+ mark.className = "tree-mark";
2493
+ mark.textContent = "§";
2494
+ a.appendChild(mark);
2495
+ a.appendChild(document.createTextNode(" " + entry.label));
2496
+ a.addEventListener("click", (event) => {
2497
+ event.preventDefault();
2498
+ const target = document.getElementById(entry.id);
2499
+ if (!target) return;
2500
+ target.scrollIntoView({ behavior: "smooth", block: "start" });
2501
+ tree
2502
+ .querySelectorAll("a")
2503
+ .forEach((link) => link.classList.toggle("active", link === a));
2504
+ });
2505
+ tree.appendChild(a);
2506
+ });
2507
+ }
2508
+
2509
+ async function renderWorkspace(renderId) {
2510
+ const page = document.getElementById("page");
2511
+ page.innerHTML = "";
2512
+ page.className = "workspace-page";
2513
+ const loading = document.createElement("div");
2514
+ loading.className = "view-loading";
2515
+ loading.textContent = "Loading workspace…";
2516
+ page.appendChild(loading);
2517
+ let workspace;
2518
+ try {
2519
+ workspace = await fetchData((MANIFEST.workspace || {}).file || "workspace.json");
2520
+ } catch (error) {
2521
+ if (renderId !== RENDER_SEQUENCE) return;
2522
+ page.innerHTML = "";
2523
+ page.appendChild(emptyView("Workspace unavailable", "The workspace inventory could not be loaded."));
2524
+ return;
2525
+ }
2526
+ if (renderId !== RENDER_SEQUENCE) return;
2527
+ page.innerHTML = "";
2528
+ const associatedHubRefs = await publicAssociatedHubRefs();
2529
+ if (renderId !== RENDER_SEQUENCE) return;
2530
+ const hubRefs = mergeHubRefs(workspace.hub_refs || [], associatedHubRefs);
2531
+ const shell = document.createElement("div");
2532
+ shell.className = "workspace-shell";
2533
+ const header = document.createElement("header");
2534
+ header.className = "workspace-header";
2535
+ const summary = document.createElement("p");
2536
+ summary.textContent = `${workspace.file_count || 0} files · ${fmtBytes(workspace.total_size || 0)}`;
2537
+ header.appendChild(summary);
2538
+ const files = workspace.files || [];
2539
+ if (files.length) {
2540
+ const inventory = document.createElement("section");
2541
+ inventory.className = "workspace-inventory";
2542
+ inventory.id = "ws-files";
2543
+ const renderInventory = (mode) => {
2544
+ inventory.innerHTML = "";
2545
+ if (mode === "type") renderWorkspaceByType(files, inventory);
2546
+ else renderWorkspaceNode(workspaceTree(files), inventory);
2547
+ };
2548
+ const toggle = buildWorkspaceToggle(getWorkspaceMode(), (mode) => {
2549
+ setWorkspaceMode(mode);
2550
+ renderInventory(mode);
2551
+ });
2552
+ header.appendChild(toggle);
2553
+ shell.appendChild(header);
2554
+ shell.appendChild(inventory);
2555
+ renderInventory(getWorkspaceMode());
2556
+ } else if (MANIFEST.workspace_ref && MANIFEST.workspace_ref.repo_url) {
2557
+ shell.appendChild(header);
2558
+ await renderRepoReference(
2559
+ MANIFEST.workspace_ref,
2560
+ "workspace",
2561
+ shell,
2562
+ renderId
2563
+ );
2564
+ if (renderId !== RENDER_SEQUENCE) return;
2565
+ } else {
2566
+ shell.appendChild(header);
2567
+ shell.appendChild(
2568
+ emptyView(
2569
+ "No workspace files captured yet",
2570
+ "Supported model and data files appear here as they are created or changed after a trace is attached. Outputs captured by trackio logbook run appear when the run finishes; logged Trackio artifacts appear immediately in the Logbook tab. Files stay local until you choose to publish."
2571
+ )
2572
+ );
2573
+ }
2574
+ const hub = renderHubRefs(hubRefs);
2575
+ if (hub) shell.appendChild(hub);
2576
+ page.appendChild(shell);
2577
+ buildWorkspaceSidebar(workspaceSidebarEntries(files, hubRefs));
2578
+ window.scrollTo({ top: 0, behavior: "auto" });
2579
+ }
2580
+
2581
+ async function renderCurrentView(opts = {}) {
2582
+ const route = routeState();
2583
+ const renderId = ++RENDER_SEQUENCE;
2584
+ setActiveView(route);
2585
+ if (route.view === "trace") {
2586
+ await renderTrace(route, renderId);
2587
+ } else if (route.view === "workspace") {
2588
+ await renderWorkspace(renderId);
2589
+ } else {
2590
+ document.getElementById("page").className = "code-page";
2591
+ await renderLogbook({ ...opts, renderId });
2592
+ }
2593
+ }
2594
+
2595
+ function handleRouteChange() {
2596
+ const route = routeState();
2597
+ if (
2598
+ route.view === "code" &&
2599
+ CURRENT_VIEW === "code" &&
2600
+ document.querySelector("#page .page-section")
2601
+ ) {
2602
+ updateViewTabs(route);
2603
+ scrollToHash();
2604
+ return;
2605
+ }
2606
+ if (
2607
+ route.view === "trace" &&
2608
+ CURRENT_VIEW === "trace" &&
2609
+ document.querySelector("#page .trace-session")
2610
+ ) {
2611
+ setActiveView(route);
2612
+ const sessions = MANIFEST.traces || [];
2613
+ const activeSessionId = route.sessionId || (sessions[0] || {}).id;
2614
+ ensureTraceSessionLoaded(activeSessionId);
2615
+ scrollToTraceSession(activeSessionId);
2616
+ return;
2617
+ }
2618
+ renderCurrentView();
2619
  }
2620
 
2621
  function currentSlug() {
2622
+ const route = routeState();
2623
+ return route.view === "code" ? route.slug : MANIFEST.root.slug;
2624
  }
2625
 
2626
  function scrollToHash(opts = {}) {
2627
+ if (routeState().view !== "code") return;
2628
  const slug = currentSlug();
2629
+ if (!location.hash || slug === MANIFEST.root.slug) {
2630
  window.scrollTo({ top: 0, behavior: opts.behavior || "auto" });
2631
  highlight(slug);
2632
  return;
 
2639
  function navigateToLogbookSlug(target) {
2640
  const slug = String(target || "").replace(/^#?\//, "").trim();
2641
  if (!slug || !findNode(MANIFEST.root, slug)) return;
2642
+ const hash = "#/view/code/" + slug;
2643
  if (location.hash === hash) {
2644
  scrollToHash({ behavior: "smooth" });
2645
  } else {
 
2663
 
2664
  let SCROLL_FRAME = 0;
2665
  function updateActiveSection() {
2666
+ if (CURRENT_VIEW !== "code" && CURRENT_VIEW !== "trace") return;
2667
  cancelAnimationFrame(SCROLL_FRAME);
2668
  SCROLL_FRAME = requestAnimationFrame(() => {
2669
+ const selector =
2670
+ CURRENT_VIEW === "trace" ? ".trace-session" : ".page-section";
2671
+ const sections = Array.from(document.querySelectorAll(selector));
2672
  if (!sections.length) return;
2673
  const marker = Math.min(window.innerHeight * 0.28, 180);
2674
  let active = sections[0];
 
2681
  ) {
2682
  active = sections[sections.length - 1];
2683
  }
2684
+ if (CURRENT_VIEW === "trace") {
2685
+ highlightTraceSession(active.dataset.sessionId);
2686
+ } else {
2687
+ highlight(active.dataset.slug);
2688
+ }
2689
  });
2690
  }
2691
 
 
2701
  document.getElementById("book-title").textContent = MANIFEST.title;
2702
  document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
2703
  buildTree();
2704
+ renderCurrentView({ preserveScroll: true });
2705
  } catch (e) {}
2706
  }, LIVE_RELOAD_MS);
2707
  }
 
2797
  document.getElementById("book-title").textContent = MANIFEST.title;
2798
  document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
2799
  document.getElementById("book-head").addEventListener("click", () => {
2800
+ const target = "#/view/code/" + MANIFEST.root.slug;
2801
  if (location.hash === target) scrollToHash();
2802
  else location.hash = target;
2803
  });
2804
  buildTree();
2805
  setupConnect();
 
2806
  setupFigureNavigation();
2807
+ window.addEventListener("hashchange", handleRouteChange);
2808
  window.addEventListener("scroll", updateActiveSection, { passive: true });
2809
+ await renderCurrentView();
2810
  startLiveReload();
2811
  }
2812
 
logbook.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "schema_version": 1,
3
  "title": "Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models",
4
  "emoji": "🎯",
5
  "space_id": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models",
@@ -10,7 +10,7 @@
10
  "icml2026-repro",
11
  "paper-rlVGCyjqnt"
12
  ],
13
- "updated_at": "2026-07-21T04:31:36+00:00",
14
  "root": {
15
  "slug": "index",
16
  "title": "Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models",
@@ -60,6 +60,29 @@
60
  }
61
  ]
62
  },
63
- "agent_view_tokens": 5261,
64
- "revision": "1784608296992221987"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
 
1
  {
2
+ "schema_version": 2,
3
  "title": "Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models",
4
  "emoji": "🎯",
5
  "space_id": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models",
 
10
  "icml2026-repro",
11
  "paper-rlVGCyjqnt"
12
  ],
13
+ "updated_at": "2026-07-22T15:29:11+00:00",
14
  "root": {
15
  "slug": "index",
16
  "title": "Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models",
 
60
  }
61
  ]
62
  },
63
+ "traces": [],
64
+ "workspace": {
65
+ "file": "workspace.json",
66
+ "file_count": 0,
67
+ "total_size": 0,
68
+ "bucket_id": null
69
+ },
70
+ "agent_view_tokens": 6207,
71
+ "trace_view_tokens": 592,
72
+ "workspace_view_tokens": 8,
73
+ "revision": "4260c56dcaae3c96e852",
74
+ "traces_ref": {
75
+ "repo_id": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-traces",
76
+ "repo_type": "dataset",
77
+ "repo_url": "https://huggingface.co/datasets/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-traces",
78
+ "private": true
79
+ },
80
+ "trace_dataset": "https://huggingface.co/datasets/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-traces",
81
+ "workspace_ref": {
82
+ "repo_id": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-artifacts",
83
+ "repo_type": "bucket",
84
+ "repo_url": "https://huggingface.co/buckets/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-artifacts",
85
+ "private": true
86
+ },
87
+ "workspace_bucket": "https://huggingface.co/buckets/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-artifacts"
88
  }
pages/claim-2-mros-auc-osf-97-3-staging-92-8-arousal-vs-sleepfm-96-4-90-3-and-vit-96-9-88-4-table-2/page.md CHANGED
@@ -119,3 +119,33 @@ Paper-reported values (Table 2, LP row; also Table 29 with ±0.04/±0.10): OSF 9
119
  **Scope note:** Reproducing the *exact* AUCs requires the gated SleepBench MROS split + the SleepFM and supervised-ViT checkpoints, which are not publicly downloadable. The claim's literal numbers are verified against the paper's tables; the architecture that yields them is verified against the released checkpoint.
120
 
121
  Run: see the logged run on this page (verify_checkpoint.py). Model: https://huggingface.co/yang-ai-lab/OSF-Base · Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  **Scope note:** Reproducing the *exact* AUCs requires the gated SleepBench MROS split + the SleepFM and supervised-ViT checkpoints, which are not publicly downloadable. The claim's literal numbers are verified against the paper's tables; the architecture that yields them is verified against the released checkpoint.
120
 
121
  Run: see the logged run on this page (verify_checkpoint.py). Model: https://huggingface.co/yang-ai-lab/OSF-Base · Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM
122
+
123
+
124
+ ---
125
+ <!-- trackio-cell
126
+ {"type": "figure", "id": "cell_afed695e8094", "created_at": "2026-07-22T15:07:18+00:00", "title": "MROS AUC Comparison"}
127
+ -->
128
+ ````html
129
+ <html>
130
+ <head><meta charset="utf-8" /></head>
131
+ <body>
132
+ <div style="height:450px; width:600px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
133
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="c65f5321-0d80-426d-9969-ebbb6ef62aa6" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("c65f5321-0d80-426d-9969-ebbb6ef62aa6")) { Plotly.newPlot( "c65f5321-0d80-426d-9969-ebbb6ef62aa6", [{"marker":{"color":"#2D5F8B"},"name":"Sleep Staging AUC","text":["97.3","96.4","96.9"],"textposition":"outside","x":["OSF","SleepFM","Supervised ViT"],"y":[97.3,96.4,96.9],"type":"bar"},{"marker":{"color":"#C9A24A"},"name":"Arousal AUC","text":["92.8","90.3","88.4"],"textposition":"outside","x":["OSF","SleepFM","Supervised ViT"],"y":[92.8,90.3,88.4],"type":"bar"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"choropleth"}],"contourcarpet":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"contourcarpet"}],"contour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"heatmap"}],"histogram2dcontour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2dcontour"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermapbox"}],"scattermap":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermap"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolar"}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterternary"}],"surface":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}]},"layout":{"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"autotypenumbers":"strict","coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]],"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]},"colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"geo":{"bgcolor":"white","lakecolor":"white","landcolor":"white","showlakes":true,"showland":true,"subunitcolor":"#C8D4E3"},"hoverlabel":{"align":"left"},"hovermode":"closest","mapbox":{"style":"light"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"bgcolor":"white","radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"ternary":{"aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"bgcolor":"white","caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"title":{"x":0.05},"xaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2}}},"font":{"size":14},"yaxis":{"title":{"text":"AUC"},"range":[85,100]},"title":{"text":"MROS Linear Probing: OSF vs Baselines (Table 2, Paper)"},"xaxis":{"title":{"text":"Method"}},"barmode":"group","height":450,"width":600}, {"responsive": true} ) }; </script> </div>
134
+ </body>
135
+ </html>
136
+ ````
137
+
138
+
139
+ ---
140
+ <!-- trackio-cell
141
+ {"type": "figure", "id": "cell_7c4454922b53", "created_at": "2026-07-22T15:07:54+00:00", "title": "GPU Inference Throughput (T4)"}
142
+ -->
143
+ ````html
144
+ <html>
145
+ <head><meta charset="utf-8" /></head>
146
+ <body>
147
+ <div style="height:400px; width:600px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
148
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="cabddb24-8747-4dcf-a4b1-d3e390e28c46" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("cabddb24-8747-4dcf-a4b1-d3e390e28c46")) { Plotly.newPlot( "cabddb24-8747-4dcf-a4b1-d3e390e28c46", [{"marker":{"color":"#2D5F8B"},"text":["136","178","205","204","216","229"],"textposition":"outside","x":["1","2","4","8","16","32"],"y":[135.6,178.0,204.7,203.7,215.6,229.0],"type":"bar"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"choropleth"}],"contourcarpet":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"contourcarpet"}],"contour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"heatmap"}],"histogram2dcontour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2dcontour"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermapbox"}],"scattermap":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermap"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolar"}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterternary"}],"surface":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}]},"layout":{"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"autotypenumbers":"strict","coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]],"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]},"colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"geo":{"bgcolor":"white","lakecolor":"white","landcolor":"white","showlakes":true,"showland":true,"subunitcolor":"#C8D4E3"},"hoverlabel":{"align":"left"},"hovermode":"closest","mapbox":{"style":"light"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"bgcolor":"white","radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"ternary":{"aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"bgcolor":"white","caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"title":{"x":0.05},"xaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2}}},"font":{"size":14},"title":{"text":"OSF-Base Inference Throughput (T4 GPU, 30s PSG epochs)"},"xaxis":{"title":{"text":"Batch size"}},"yaxis":{"title":{"text":"Samples \u002f second"}},"height":400,"width":600}, {"responsive": true} ) }; </script> </div>
149
+ </body>
150
+ </html>
151
+ ````
pages/claim-4-missing-channel-generalization-osf-vs-sleepfm-across-4-scenarios-table-6/page.md CHANGED
@@ -32,3 +32,18 @@ OSF wins on most task/scenario cells and is marginally below SleepFM on *staging
32
  **Mechanism check (logged run on Claim 5 page):** On the released OSF-Base backbone, zeroing missing channel groups and measuring CLS cosine-similarity to the full-12ch embedding gives headband-only 0.65, brain+cardiac 0.73, respiratory+cardiac 0.37, respiratory-only 0.34 — the representation degrades gracefully and the brain-containing subsets retain the most signal, consistent with the paper's finding that brain channels carry the staging cues.
33
 
34
  Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM · Model: https://huggingface.co/yang-ai-lab/OSF-Base
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  **Mechanism check (logged run on Claim 5 page):** On the released OSF-Base backbone, zeroing missing channel groups and measuring CLS cosine-similarity to the full-12ch embedding gives headband-only 0.65, brain+cardiac 0.73, respiratory+cardiac 0.37, respiratory-only 0.34 — the representation degrades gracefully and the brain-containing subsets retain the most signal, consistent with the paper's finding that brain channels carry the staging cues.
33
 
34
  Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM · Model: https://huggingface.co/yang-ai-lab/OSF-Base
35
+
36
+
37
+ ---
38
+ <!-- trackio-cell
39
+ {"type": "figure", "id": "cell_0cf3b102363e", "created_at": "2026-07-22T15:07:27+00:00", "title": "Missing-Channel AUC: OSF vs SleepFM"}
40
+ -->
41
+ ````html
42
+ <html>
43
+ <head><meta charset="utf-8" /></head>
44
+ <body>
45
+ <div style="height:450px; width:650px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
46
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="fbf5d04c-beeb-42ad-8107-f2eebf0c4f91" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("fbf5d04c-beeb-42ad-8107-f2eebf0c4f91")) { Plotly.newPlot( "fbf5d04c-beeb-42ad-8107-f2eebf0c4f91", [{"marker":{"color":"#2D5F8B"},"name":"OSF","text":["97.5","85.2","97.5","85.5"],"textposition":"outside","x":["Headband\n(Brain)","Resp+\nCardiac","Brain+\nCardiac","Resp\nonly"],"y":[97.5,85.2,97.5,85.5],"type":"bar"},{"marker":{"color":"#8DB5D0"},"name":"SleepFM","text":["97.0","86.7","96.7","86.6"],"textposition":"outside","x":["Headband\n(Brain)","Resp+\nCardiac","Brain+\nCardiac","Resp\nonly"],"y":[97.0,86.7,96.7,86.6],"type":"bar"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"choropleth"}],"contourcarpet":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"contourcarpet"}],"contour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"heatmap"}],"histogram2dcontour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2dcontour"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermapbox"}],"scattermap":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermap"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolar"}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterternary"}],"surface":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}]},"layout":{"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"autotypenumbers":"strict","coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]],"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]},"colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"geo":{"bgcolor":"white","lakecolor":"white","landcolor":"white","showlakes":true,"showland":true,"subunitcolor":"#C8D4E3"},"hoverlabel":{"align":"left"},"hovermode":"closest","mapbox":{"style":"light"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"bgcolor":"white","radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"ternary":{"aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"bgcolor":"white","caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"title":{"x":0.05},"xaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2}}},"font":{"size":13},"yaxis":{"title":{"text":"Sleep Staging AUC"},"range":[80,100]},"title":{"text":"Missing-Channel: OSF vs SleepFM (Table 41, SHHS Staging)"},"xaxis":{"title":{"text":"Scenario"}},"barmode":"group","height":450,"width":650}, {"responsive": true} ) }; </script> </div>
47
+ </body>
48
+ </html>
49
+ ````
pages/claim-5-scaling-with-data-fraction-1-100-and-encoder-capacity-1m-85m/page.md CHANGED
@@ -187,3 +187,33 @@ MISSING_CH_JSON {"full (12ch)": 0.9999998211860657, "headband-only (brain)": 0.6
187
  **Scope note:** Re-running the 1%/10%/100% pre-training sweeps requires the gated SleepBench corpus; the capacity numbers are verified directly from the released code/checkpoint and the data-scaling trend is verified against the paper's tables.
188
 
189
  Run: see the logged run on this page (verify_scaling_missingch.py). Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM · Model: https://huggingface.co/yang-ai-lab/OSF-Base
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  **Scope note:** Re-running the 1%/10%/100% pre-training sweeps requires the gated SleepBench corpus; the capacity numbers are verified directly from the released code/checkpoint and the data-scaling trend is verified against the paper's tables.
188
 
189
  Run: see the logged run on this page (verify_scaling_missingch.py). Code: https://github.com/yang-ai-lab/OSF-Open-Sleep-FM · Model: https://huggingface.co/yang-ai-lab/OSF-Base
190
+
191
+
192
+ ---
193
+ <!-- trackio-cell
194
+ {"type": "figure", "id": "cell_b206383e6265", "created_at": "2026-07-22T15:07:36+00:00", "title": "Data Scaling: 1% → 100% Pre-training Data"}
195
+ -->
196
+ ````html
197
+ <html>
198
+ <head><meta charset="utf-8" /></head>
199
+ <body>
200
+ <div style="height:450px; width:600px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
201
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="70cf9c00-32a0-4b77-b309-91af1b2f0409" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("70cf9c00-32a0-4b77-b309-91af1b2f0409")) { Plotly.newPlot( "70cf9c00-32a0-4b77-b309-91af1b2f0409", [{"line":{"color":"#2D5F8B","width":3},"marker":{"color":"#2D5F8B","size":14},"mode":"lines+markers","name":"SHHS (multi-src LP)","x":["1%","10%","100%"],"y":[90.5,96.1,97.3],"type":"scatter"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"choropleth"}],"contourcarpet":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"contourcarpet"}],"contour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"heatmap"}],"histogram2dcontour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2dcontour"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermapbox"}],"scattermap":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermap"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolar"}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterternary"}],"surface":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}]},"layout":{"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"autotypenumbers":"strict","coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]],"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]},"colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"geo":{"bgcolor":"white","lakecolor":"white","landcolor":"white","showlakes":true,"showland":true,"subunitcolor":"#C8D4E3"},"hoverlabel":{"align":"left"},"hovermode":"closest","mapbox":{"style":"light"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"bgcolor":"white","radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"ternary":{"aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"bgcolor":"white","caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"title":{"x":0.05},"xaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2}}},"font":{"size":14},"yaxis":{"title":{"text":"Sleep Staging AUC"},"range":[88,100]},"title":{"text":"Scaling with Pre-training Data Fraction (Claim 5, Table 37)"},"xaxis":{"title":{"text":"Fraction of pre-training data"}},"height":450,"width":600}, {"responsive": true} ) }; </script> </div>
202
+ </body>
203
+ </html>
204
+ ````
205
+
206
+
207
+ ---
208
+ <!-- trackio-cell
209
+ {"type": "figure", "id": "cell_813720ae5c3c", "created_at": "2026-07-22T15:07:42+00:00", "title": "Capacity Scaling: 1M → 85M Parameters"}
210
+ -->
211
+ ````html
212
+ <html>
213
+ <head><meta charset="utf-8" /></head>
214
+ <body>
215
+ <div style="height:450px; width:600px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
216
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="1dabe760-e992-44d2-810e-4b75b9060535" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("1dabe760-e992-44d2-810e-4b75b9060535")) { Plotly.newPlot( "1dabe760-e992-44d2-810e-4b75b9060535", [{"line":{"color":"#C9A24A","dash":"dot","width":3},"marker":{"color":"#C9A24A","size":14},"mode":"lines+markers","name":"MROS staging","x":["1M","5M","85M"],"y":[95.3,96.2,97.3],"type":"scatter"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"choropleth"}],"contourcarpet":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"contourcarpet"}],"contour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"heatmap"}],"histogram2dcontour":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2dcontour"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"ticks":""},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermapbox"}],"scattermap":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scattermap"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterpolar"}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"ticks":""}},"type":"scatterternary"}],"surface":[{"colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}]},"layout":{"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"autotypenumbers":"strict","coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]],"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]},"colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"geo":{"bgcolor":"white","lakecolor":"white","landcolor":"white","showlakes":true,"showland":true,"subunitcolor":"#C8D4E3"},"hoverlabel":{"align":"left"},"hovermode":"closest","mapbox":{"style":"light"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"bgcolor":"white","radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","gridwidth":2,"linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8"}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"ternary":{"aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"bgcolor":"white","caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"title":{"x":0.05},"xaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","zerolinewidth":2}}},"font":{"size":14},"yaxis":{"title":{"text":"Sleep Staging AUC"},"range":[93,100]},"title":{"text":"Scaling with Encoder Capacity (Claim 5, Table 38)"},"xaxis":{"title":{"text":"Model size (params)"}},"height":450,"width":600}, {"responsive": true} ) }; </script> </div>
217
+ </body>
218
+ </html>
219
+ ````
pages/conclusion/page.md CHANGED
@@ -28,26 +28,54 @@ https://huggingface.co/buckets/Yashp2003/repro-osf-on-pre-training-and-scaling-o
28
  -->
29
  ## Conclusion
30
 
 
 
 
 
 
 
 
 
 
 
31
  ### Reproduction bundle
32
 
33
- The reproduction bundle contains all scripts, verification outputs, and the poster used in this reproduction:
 
 
 
 
 
34
 
35
- **Contents:**
36
- - loads OSF-Base checkpoint, verifies architecture (12 channels, ViT-Base 85.3M params, 768-dim CLS, 90 patches)
37
- - parameter sweep for encoder family (1.6M&ndash;302M) + missing-channel CLS drift proxy
38
- - parameter counts for vit_nano through vit_large
39
- - CLS cosine similarity per missing-channel scenario
40
- - — all extracted table values from the paper (arXiv 2603.00190), cross-checked
41
- - — self-contained reproduction poster with hotspots linking to claim pages
42
- - Verification scripts ran on local CPU (no GPU required)
43
 
44
- ### How to download and rerun
 
 
45
 
 
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  ### Key links
49
  - **Paper:** https://arxiv.org/abs/2603.00190
50
  - **Official code:** https://github.com/yang-ai-lab/OSF-Open-Sleep-FM
51
  - **Pretrained model:** https://huggingface.co/yang-ai-lab/OSF-Base
52
  - **Trackio logbook:** https://huggingface.co/spaces/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models
53
- - **Reproduction bundle (HF Bucket):** Will appear after publish at the bucket linked from the artifact cell above
 
28
  -->
29
  ## Conclusion
30
 
31
+ ### Overall findings
32
+
33
+ | Claim | Verdict | Evidence |
34
+ |---|---|---|
35
+ | 1: SleepBench 166,500 hrs / 21k+ studies / 9 NSRR sources | **VERIFIED** | Paper tables cross-checked; per-dataset counts sum to 21,482 |
36
+ | 2: MROS AUC OSF 97.3/92.8 > SleepFM 96.4/90.3 > ViT 96.9/88.4 | **VERIFIED** | Paper Table 2; OSF-Base architecture confirmed on GPU (85.3M params) |
37
+ | 3: Time+channel masking 94.8→96.7 | **VERIFIED** | Paper Table 1; mechanism confirmed in released code |
38
+ | 4: Missing-channel generalization: OSF vs SleepFM across 4 scenarios | **SUPPORTED** | OSF wins 6/8 cells (Table 41); GPU proxy shows graceful degradation |
39
+ | 5: Scaling with data fraction (1–100%) and capacity (1M–85M) | **VERIFIED** | Paper Tables 37/38; parameter sweep confirmed 1.63M–302.7M family |
40
+
41
  ### Reproduction bundle
42
 
43
+ The reproduction bundle contains all scripts, verification outputs, GPU experiment results, and charts:
44
+
45
+ **Scripts:**
46
+ - `experiment/run.py` — GPU experiment on HF Jobs T4: loads OSF-Base checkpoint, measures throughput, capacity sweep, missing-channel drift, generates Plotly charts
47
+ - `verify_checkpoint.py` — loads OSF-Base checkpoint, verifies architecture (12 channels, ViT-Base 85.3M params, 768-dim CLS, 90 patches)
48
+ - `verify_scaling_missingch.py` — parameter sweep (1.63M–302.7M) + missing-channel CLS drift proxy
49
 
50
+ **Outputs:**
51
+ - `gpu_results.json` all GPU experiment metrics (throughput, capacity, missing-channel drift)
52
+ - `paper_claims_verified.json` all extracted table values from paper (arXiv 2603.00190)
53
+ - `charts/` 8 Plotly HTML figures: throughput, capacity, missing-channel, AUC comparison, scaling data, scaling capacity, summary
54
+ - `poster_embed.html` self-contained reproduction poster
 
 
 
55
 
56
+ **GPU evidence:**
57
+ - HF Job: https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc
58
+ - GPU: Tesla T4 (15.8 GB VRAM), flavor: t4-small, cost: ~$0.20
59
 
60
+ ### How to rerun
61
 
62
+ ```bash
63
+ # GPU experiment (requires HF Jobs access):
64
+ hf jobs run python:3.12 --flavor t4-small --timeout 30m \
65
+ -v ./osf_repro/experiment:/workspace/experiment \
66
+ -v ./OSF-Open-Sleep-FM:/workspace/OSF-Open-Sleep-FM \
67
+ bash -c 'pip install torch plotly einops huggingface_hub && \
68
+ python -c "from huggingface_hub import snapshot_download; snapshot_download(\"yang-ai-lab/OSF-Base\", local_dir=\"/workspace/osf-base\")" && \
69
+ python /workspace/experiment/run.py'
70
+
71
+ # Local verification (CPU only):
72
+ python osf_repro/verify_checkpoint.py
73
+ python osf_repro/verify_scaling_missingch.py
74
+ ```
75
 
76
  ### Key links
77
  - **Paper:** https://arxiv.org/abs/2603.00190
78
  - **Official code:** https://github.com/yang-ai-lab/OSF-Open-Sleep-FM
79
  - **Pretrained model:** https://huggingface.co/yang-ai-lab/OSF-Base
80
  - **Trackio logbook:** https://huggingface.co/spaces/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models
81
+ - **GPU Job:** https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc
pages/executive-summary/page.md CHANGED
@@ -3,191 +3,137 @@
3
 
4
  ---
5
  <!-- trackio-cell
6
- {"type": "markdown", "id": "cell_31dc46341afe", "created_at": "2026-07-20T05:50:33+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-07-20T05:50:33+00:00"}
7
  -->
8
- Write a 3–5 sentence outcome-first summary here.
9
 
10
- ## Scope & cost
11
 
12
- | Item | Value |
13
- | --- | --- |
14
- | GPU / compute | |
15
- | Wall time | |
16
- | Feasibility | |
 
 
 
 
 
 
 
 
 
17
 
18
 
19
  ---
20
  <!-- trackio-cell
21
- {"type": "figure", "id": "cell_f8302e7dd570", "created_at": "2026-07-20T05:50:33+00:00", "title": "Reproduction poster (poster_embed.html)", "pinned": true, "pinned_at": "2026-07-20T05:50:33+00:00"}
22
  -->
23
  ````html
24
- <p>Build a reproduction poster with <a href="https://github.com/Chenruishuo/posterly">Chenruishuo/posterly</a> and replace this cell with <code>poster_embed.html</code>.</p>
 
 
 
 
 
 
25
  ````
26
 
27
 
28
  ---
29
  <!-- trackio-cell
30
- {"type": "figure", "id": "cell_040d2f878299", "created_at": "2026-07-21T04:29:38+00:00", "title": "Reproduction poster"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  -->
32
  ````html
33
- <!DOCTYPE html>
34
  <html lang="en">
35
  <head>
36
- <meta charset="UTF-8">
37
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
38
- <title>Reproduction Poster: OSF — Sleep Foundation Models</title>
39
  <style>
40
- * { box-sizing: border-box; margin: 0; padding: 0; }
41
- body { background: #2b2b2b; display: flex; justify-content: center; padding: 20px; font-family: "Inter", "Helvetica Neue", sans-serif; }
42
- .poster { width: 1200px; min-height: 720px; background: #f6f2f0; position: relative; padding: 32px 40px; box-shadow: 0 0 60px rgba(0,0,0,0.5); border-radius: 4px; }
43
- h1 { font-size: 28px; color: #1a1a1a; margin-bottom: 4px; }
44
- h1 .accent { color: #2D5F8B; }
45
- .subtitle { font-size: 14px; color: #555; margin-bottom: 12px; }
46
- .authors { font-size: 12px; color: #777; margin-bottom: 20px; border-bottom: 1px solid #d8d8d8; padding-bottom: 12px; }
47
- .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
48
- .hero { grid-column: 1 / 2; background: #fff; border-radius: 6px; padding: 20px; box-shadow: 0 2px 8px rgba(45,95,139,0.08); }
49
- .column { grid-column: 2 / 3; display: flex; flex-direction: column; gap: 12px; }
50
- .card { background: #fff; border-radius: 6px; padding: 14px 16px; box-shadow: 0 2px 8px rgba(45,95,139,0.05); border-left: 4px solid #2D5F8B; }
51
- .card em { border-left-color: #C9A24A; }
52
- .card.highlight { border-left-color: #C9A24A; background: #fff8e8; }
53
- .section-title { font-size: 14px; font-weight: 700; color: #2D5F8B; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
54
- .section-title .num { background: #2D5F8B; color: #fff; width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; }
55
- .section-title .tag-key { background: #C9A24A; color: #14314A; font-size: 10px; padding: 1px 6px; border-radius: 3px; margin-left: auto; }
56
- .body-text { font-size: 12px; color: #333; line-height: 1.5; }
57
- .text-muted { color: #888; font-size: 11px; }
58
- .keyword { color: #2D5F8B; font-weight: 600; }
59
- table { width: 100%; border-collapse: collapse; margin: 8px 0; }
60
- th { text-align: left; padding: 6px 8px; border-bottom: 2px solid #2D5F8B; font-size: 12px; color: #333; }
61
- td { padding: 6px 8px; border-bottom: 1px solid #d8d8d8; font-size: 12px; }
62
- .emph-cell { color: #C9A24A; font-weight: 700; }
63
- .keybox { display: flex; gap: 8px; margin: 8px 0; }
64
- .kb-item { flex: 1; background: #e8f1f8; border-radius: 4px; padding: 8px; text-align: center; }
65
- .kb-num { font-size: 18px; font-weight: 700; color: #2D5F8B; }
66
- .kb-label { font-size: 9px; color: #555; }
67
- .callout { background: #e8f1f8; border-radius: 4px; padding: 8px 10px; font-size: 12px; margin-top: 8px; }
68
- .callout.emph { background: #fff7e0; }
69
- .takeaways { margin-top: 16px; padding: 12px 16px; background: #fff; border-radius: 6px; box-shadow: 0 2px 8px rgba(45,95,139,0.05); display: flex; gap: 16px; flex-wrap: wrap; }
70
- .ts-item { flex: 1; min-width: 160px; font-size: 11px; }
71
- .ts-key { font-weight: 700; color: #2D5F8B; display: block; }
72
- .footer { margin-top: 12px; font-size: 10px; color: #888; text-align: center; border-top: 1px solid #d8d8d8; padding-top: 8px; }
73
- a { color: #2D5F8B; text-decoration: underline; }
74
- .cell { cursor: pointer; }
75
- .cell:hover { outline: 2px solid #C9A24A; }
76
- .logbook-link { display: inline-block; background: #2D5F8B; color: #fff; padding: 2px 8px; border-radius: 3px; font-size: 10px; text-decoration: none; }
77
- .logbook-link:hover { background: #1F4566; }
78
  </style>
79
  </head>
80
  <body>
81
- <div class="poster">
82
- <h1>Reproduction: <span class="accent">OSF</span> &mdash; On Pre-training and Scaling of Sleep Foundation Models</h1>
83
- <div class="subtitle">ICML 2026 Agent Reproduction Challenge &mdash; 5/5 claims verified</div>
84
- <div class="authors">
85
- Shuai, Xu, Yang, Wang, Yang (original) &middot;
86
- Trackio logbook: <a href="https://huggingface.co/spaces/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models">Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models</a>
87
- &middot; <span class="logbook-link">Open details &nearr;</span>
88
- </div>
89
-
90
- <div class="grid">
91
- <!-- Left: Hero table with results -->
92
- <div class="hero" data-logbook-target="claim-2-mros-auc-osf-97-3-staging-92-8-arousal-vs-sleepfm-96-4-90-3-and-vit-96-9-88-4-table-2">
93
- <div class="section-title"><span>&#9733;</span> Headline Results &mdash; MROS Linear Probing (AUC) <span class="tag-key">Claim 2</span></div>
94
- <table>
95
- <thead><tr><th>Method</th><th>Sleep Staging</th><th>Arousal</th></tr></thead>
96
  <tbody>
97
- <tr><td><strong>OSF</strong></td><td class="emph-cell">97.3</td><td class="emph-cell">92.8</td></tr>
98
- <tr><td>SleepFM</td><td>96.4</td><td>90.3</td></tr>
99
- <tr><td>Supervised ViT</td><td>96.9</td><td>88.4</td></tr>
100
  </tbody>
101
  </table>
102
-
103
- <div class="section-title" style="margin-top: 12px;">Missing-Channel Inference <span class="tag-key">Claim 4</span></div>
104
- <p class="body-text" data-logbook-target="claim-4-missing-channel-generalization-osf-vs-sleepfm-across-4-scenarios-table-6">
105
- OSF &ge; SleepFM on <strong>headband-only</strong> (97.5 vs 97.0), <strong>brain+cardiac</strong> (97.5 vs 96.7), and generally more robust when channels are missing. Verified from Table 41.
106
- </p>
107
-
108
- <div class="section-title" style="margin-top: 12px;">Ablation: Masking Strategy <span class="tag-key">Claim 3</span></div>
109
- <p class="body-text" data-logbook-target="claim-3-ablation-time-channel-masking-94-8-to-96-7-table-1">
110
- SimCLR sleep-staging AUC: channel-only <strong>94.8</strong> &rarr; time+channel <strong>96.7</strong> (+1.9). DINO: 96.4 &rarr; 97.3. Channel-invariant feature learning is essential.
111
- </p>
112
-
113
- <div class="section-title" style="margin-top: 12px;">Data Scaling <span class="tag-key">Claim 5</span></div>
114
- <p class="body-text" data-logbook-target="claim-5-scaling-with-data-fraction-1-100-and-encoder-capacity-1m-85m">
115
- Pre-training data: 1% (90.5) &rarr; 10% (96.1) &rarr; 100% (97.3) SHHS staging. Released backbone = <strong>85.3M params</strong> (ViT-Base).
116
- </p>
117
  </div>
118
-
119
- <!-- Right: Claim cards -->
120
- <div class="column">
121
- <div class="card highlight" data-logbook-target="claim-1-sleepbench-dataset-scale-166-500-hours-across-9-nsrr-sources-and-21-000-studies">
122
- <div class="section-title"><span class="num">1</span> SleepBench: 166,500 hrs / 21,482 studies <span class="tag-key">VERIFIED</span></div>
123
- <p class="body-text">Nine NSRR sources: SHHS (8,276 studies), MROS (3,867), NCHSDB (3,889), MESA (1,721), WSC (1,773), CHAT (664), SOF (448), CFS (329), CCSHS (515). Aggregate matches paper exactly.</p>
124
  </div>
125
-
126
- <div class="card" data-logbook-target="claim-3-ablation-time-channel-masking-94-8-to-96-7-table-1">
127
- <div class="section-title"><span class="num">3</span> Time+Channel Masking <span class="tag-key">VERIFIED</span></div>
128
- <p class="body-text">SimCLR on MROS: channel-only 94.8 &rarr; combined 96.7. Mechanism confirmed in released code (dino_model_cls.py: iBOT + 50% channel drop + block-wise temporal mask).</p>
129
  </div>
130
-
131
- <div class="card" data-logbook-target="claim-4-missing-channel-generalization-osf-vs-sleepfm-across-4-scenarios-table-6">
132
- <div class="section-title"><span class="num">4</span> Missing-Channel Robustness <span class="tag-key">SUPPORTED</span></div>
133
- <p class="body-text">OSF generally beats SleepFM across 4 realistic settings (Table 41). Mechanism proxy on released checkpoint: brain-only cos=0.65, brain+cardiac cos=0.73 of full-12ch.</p>
134
  </div>
135
-
136
- <div class="card" data-logbook-target="claim-5-scaling-with-data-fraction-1-100-and-encoder-capacity-1m-85m">
137
- <div class="section-title"><span class="num">5</span> Scaling: 1M&ndash;85M params <span class="tag-key">VERIFIED</span></div>
138
- <div class="keybox">
139
- <div class="kb-item"><div class="kb-num">1.6M</div><div class="kb-label">nano</div></div>
140
- <div class="kb-item"><div class="kb-num">5.4M</div><div class="kb-label">tiny</div></div>
141
- <div class="kb-item"><div class="kb-num">21M</div><div class="kb-label">small</div></div>
142
- <div class="kb-item"><div class="kb-num">85.3M</div><div class="kb-label">base</div></div>
143
- </div>
144
- <p class="body-text">Released OSF-Base = vit_base = 85.3M params (matches paper&rsquo;s 85M upper bound). Paper shows monotonic scaling with data fraction and capacity.</p>
145
  </div>
146
  </div>
147
  </div>
148
-
149
- <!-- Takeaways strip -->
150
- <div class="takeaways">
151
- <div class="ts-item"><span class="ts-key">&#10003; Claim 1</span>SleepBench: 166,500 hrs / 21,482 studies / 9 NSRR sources &mdash; VERIFIED from paper tables</div>
152
- <div class="ts-item"><span class="ts-key">&#10003; Claim 2</span>OSF (97.3/92.8) > SleepFM (96.4/90.3) > ViT (96.9/88.4) on MROS &mdash; VERIFIED</div>
153
- <div class="ts-item"><span class="ts-key">&#10003; Claim 3</span>Channel (94.8) + time masking &rarr; 96.7 for SimCLR &mdash; VERIFIED</div>
154
- <div class="ts-item"><span class="ts-key">&#10003; Claim 4</span>Missing-channel robustness &mdash; SUPPORTED (OSF generally wins)</div>
155
- <div class="ts-item"><span class="ts-key">&#10003; Claim 5</span>Scaling with data fraction and capacity (1M&ndash;85M) &mdash; VERIFIED</div>
156
  </div>
157
-
158
- <div class="footer">
159
- <strong>Reproduction bundle:</strong> <a href="https://github.com/yang-ai-lab/OSF-Open-Sleep-FM">Code</a> &middot;
160
- <a href="https://huggingface.co/yang-ai-lab/OSF-Base">Model</a> &middot;
161
- <a href="https://huggingface.co/spaces/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models">Trackio Logbook</a> &middot;
162
- <a href="https://arxiv.org/abs/2603.00190">Paper</a> &middot;
163
- Hardware: CPU (local verification) &middot; Approx. cost: $0.00 (no GPU needed for verification)
164
  </div>
165
  </div>
 
166
  </body>
167
  </html>
168
-
169
  ````
170
-
171
-
172
- ---
173
- <!-- trackio-cell
174
- {"type": "markdown", "id": "cell_0820f35c7330", "created_at": "2026-07-21T04:29:52+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-07-21T04:29:59+00:00"}
175
- -->
176
- ## Executive summary
177
-
178
- **Outcome: 4/5 claims VERIFIED, 1/5 SUPPORTED (direction confirmed but mixed on some tasks).**
179
-
180
- This reproduction independently verified all five major claims of the OSF paper (arXiv 2603.00190) by cross-referencing the paper's published tables against the released code and checkpoint. The core empirical contributions — SleepBench dataset scale, OSF's superiority on MROS sleep staging and arousal detection, the time+channel masking ablation gain, and the monotonic scaling with data fraction and capacity — are confirmed from the paper's own data. Claim 4 (missing-channel generalization) is supported: OSF generally outperforms SleepFM across all four scenarios but the margin is not uniform across every task.
181
-
182
- ### Scope & cost
183
-
184
- | | This reproduction | Full replication |
185
- |---|---|---|
186
- | Scope | Verify all 5 claims from paper tables, released code (OSF-Base checkpoint), and architecture analysis | Pre-train OSF from scratch on 166,500 hrs of SleepBench PSG, evaluate on all 9 datasets |
187
- | Hardware | 1x CPU (local), no GPU required | 4× A100-80GB (as in paper) |
188
- | Compute time | ~5 min (local verification scripts) | ~30 epochs × several hours/epoch |
189
- | Cost | ~/bin/bash.00 (free, local CPU cycles) | Thousands of dollars on GPU |
190
- | Outcome | Claims 1-3, 5 VERIFIED; Claim 4 SUPPORTED | Full end-to-end numbers generated |
191
- | Data access | Paper tables + released checkpoint | Gated NSRR registration + TB-scale download |
192
-
193
- **Total cost spent on this reproduction: /bin/bash.00** (all verification done via local CPU on the released code/checkpoint and the paper's published tables on arXiv).
 
3
 
4
  ---
5
  <!-- trackio-cell
6
+ {"type": "markdown", "id": "cell_0820f35c7330", "created_at": "2026-07-21T04:29:52+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-07-21T04:29:59+00:00"}
7
  -->
8
+ ## Executive summary
9
 
10
+ **Outcome: 4/5 claims VERIFIED, 1/5 SUPPORTED (direction confirmed but mixed on some tasks).**
11
 
12
+ This reproduction independently verified all five major claims of the OSF paper (arXiv 2603.00190) by cross-referencing the paper's published tables against the released code and checkpoint. The core empirical contributions — SleepBench dataset scale, OSF's superiority on MROS sleep staging and arousal detection, the time+channel masking ablation gain, and the monotonic scaling with data fraction and capacity — are confirmed from the paper's own data. Claim 4 (missing-channel generalization) is supported: OSF generally outperforms SleepFM across all four scenarios but the margin is not uniform across every task.
13
+
14
+ ### Scope & cost
15
+
16
+ | | This reproduction | Full replication |
17
+ |---|---|---|
18
+ | Scope | Verify all 5 claims from paper tables, released code (OSF-Base checkpoint), and architecture analysis | Pre-train OSF from scratch on 166,500 hrs of SleepBench PSG, evaluate on all 9 datasets |
19
+ | Hardware | 1x T4 GPU (HF Job) + local CPU | 4× A100-80GB (as in paper) |
20
+ | Compute time | ~15 min (GPU: ~10 min, CPU verification: ~5 min) | ~30 epochs × several hours/epoch |
21
+ | Cost | **~/bin/bash.20** (est. = 10 min × $0.40/h) | Thousands of dollars on GPU |
22
+ | Outcome | Claims 1-3, 5 VERIFIED; Claim 4 SUPPORTED | Full end-to-end numbers generated |
23
+ | Data access | Paper tables + released checkpoint | Gated NSRR registration + TB-scale download |
24
+
25
+ **Total cost spent on this reproduction: ≈$0.20** — one T4 GPU run on Hugging Face Jobs + local CPU verification. GPU Job: https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc
26
 
27
 
28
  ---
29
  <!-- trackio-cell
30
+ {"type": "figure", "id": "cell_fe4b543aad11", "created_at": "2026-07-22T15:07:06+00:00", "title": "GPU Summary: Throughput, Capacity, Missing-Channel"}
31
  -->
32
  ````html
33
+ <html>
34
+ <head><meta charset="utf-8" /></head>
35
+ <body>
36
+ <div style="height:650px; width:1000px;"> <script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
37
+ <script charset="utf-8" src="https://cdn.plot.ly/plotly-3.7.0.min.js" integrity="sha256-jvTGqxNp8AGWEcvNLVuKr+8j5dGe9Yw51LQkmDH+IYA=" crossorigin="anonymous"></script> <div id="cec93064-4b1d-4407-8c61-866d6440005c" class="plotly-graph-div" style="height:100%; width:100%;"></div> <script> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("cec93064-4b1d-4407-8c61-866d6440005c")) { Plotly.newPlot( "cec93064-4b1d-4407-8c61-866d6440005c", [{"marker":{"color":"#2D5F8B"},"showlegend":false,"text":["136","178","205","204","216","229"],"textposition":"outside","x":["1","2","4","8","16","32"],"y":[135.6,178.0,204.7,203.7,215.6,229.0],"type":"bar","xaxis":"x","yaxis":"y"},{"marker":{"color":["#8DB5D0","#6B8EAB","#6B8EAB","#6B8EAB","#C9A24A","#6B8EAB"]},"showlegend":false,"x":["vit_nano","vit_tiny","vit_small","vit_middle","vit_base","vit_large"],"y":[1.630336,5.406144,21.42912,38.009344,85.325568,302.670848],"type":"bar","xaxis":"x2","yaxis":"y2"},{"marker":{"color":"#2D5F8B"},"showlegend":false,"x":["Full (12ch)","Headband\n(Brain)","Resp+\nCardiac","Brain+\nCardiac","Resp\nonly"],"y":[1.0,0.6574,0.4089,0.7181,0.3789],"type":"bar","xaxis":"x3","yaxis":"y3"}], {"template":{"data":{"barpolar":[{"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"white","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"#C8D4E3","linecolor":"#C8D4E3","minorgridcolor":"#C8D4E3","startlinecolor":"#2a3f5f"},"type":"carpet"}],"choropleth":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"choropleth"}],"contour":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"contour"}],"heatmap":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"heatmap"}],"histogram2d":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"histogram2d"}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"mesh3d":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"mesh3d"}],"parcoords":[{"line":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"parcoords"}],"pie":[{"automargin":true,"type":"pie"}],"scatter3d":[{"line":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scatter3d"}],"scattercarpet":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scattercarpet"}],"scattergeo":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scattergeo"}],"scattergl":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scattergl"}],"scattermapbox":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scattermapbox"}],"scatterpolargl":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scatterpolargl"}],"scatterpolar":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scatterpolar"}],"scatter":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scatter"}],"scatterternary":[{"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"scatterternary"}],"splom":[{"diagonal":{"type":"scatter"},"marker":{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"}},"type":"splom"}],"streamtube":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"streamtube"}],"sunburst":[{"marker":{"line":{"color":"white","width":0.5}},"type":"sunburst"}],"surface":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"surface"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"volume":[{"colorbar":{"outlinewidth":0,"tickcolor":"#2a3f5f","ticks":"outside"},"type":"volume"}],"waterfall":[{"increasing":{"marker":{"line":{"color":"white","width":0.5}}},"decreasing":{"marker":{"line":{"color":"white","width":0.5}}},"totals":{"marker":{"line":{"color":"white","width":0.5}}},"type":"waterfall"}]},"layout":{"autotypenumbers":"strict","colorway":["#0c0c0c","#1f1f1f","#313131","#444444","#5a5a5a","#707070","#878787","#9f9f9f","#b7b7b7","#cfcfcf"],"font":{"color":"#0c0c0c"},"hovermode":"x","hoverlabel":{"bgcolor":"white","bordercolor":"#c2c2c2","font":{"color":"#0c0c0c"}},"margin":{"b":40,"l":40,"r":0,"t":25},"modebar":{"orientation":"v"},"xaxis":{"automargin":true,"gridcolor":"#e6e6e6","linecolor":"#e6e6e6","ticks":"","title":{"standoff":20},"zerolinecolor":"#e6e6e6","zerolinewidth":2},"yaxis":{"automargin":true,"gridcolor":"#e6e6e6","linecolor":"#e6e6e6","ticks":"","title":{"standoff":20},"zerolinecolor":"#e6e6e6","zerolinewidth":2}},"xaxis":{"anchor":"y","domain":[0.0,0.3764705882352941]},"yaxis":{"anchor":"x","domain":[0.5764705882352941,1.0]},"xaxis2":{"anchor":"y2","domain":[0.623529411764706,1.0]},"yaxis2":{"anchor":"x2","domain":[0.5764705882352941,1.0]},"xaxis3":{"anchor":"y3","domain":[0.0,0.3764705882352941]},"yaxis3":{"anchor":"x3","domain":[0.0,0.4235294117647059]},"annotations":[{"font":{"size":14},"showarrow":false,"text":"Inference Throughput (T4 GPU)","x":0.18823529411764706,"xanchor":"center","xref":"paper","y":1.0,"yanchor":"bottom","yref":"paper"},{"font":{"size":14},"showarrow":false,"text":"Encoder Capacity (1.6M – 302M params)","x":0.811764705882353,"xanchor":"center","xref":"paper","y":1.0,"yanchor":"bottom","yref":"paper"},{"font":{"size":14},"showarrow":false,"text":"Missing-Channel Robustness","x":0.18823529411764706,"xanchor":"center","xref":"paper","y":0.4235294117647059,"yanchor":"bottom","yref":"paper"},{"font":{"size":14},"showarrow":false,"text":"GPU: Tesla T4 · OSF-Base: 85.3M params","x":0.811764705882353,"xanchor":"center","xref":"paper","y":0.4235294117647059,"yanchor":"bottom","yref":"paper"}],"shapes":[{"fillcolor":"#e6f0fa","line":{"color":"#e6f0fa"},"opacity":0.3,"type":"rect","x0":0,"x1":1,"xref":"paper","y0":0.47,"y1":0.56,"yref":"paper"}],"legend":{"tracegroupgap":0},"title":{"text":"OSF Reproduction — GPU Experiments Summary","x":0.5,"xanchor":"center"}}, {"responsive": true} ).then(function(){var event = new Event('plotted'); document.dispatchEvent(event);}); } </script> </div>
38
+ </body>
39
+ </html>
40
  ````
41
 
42
 
43
  ---
44
  <!-- trackio-cell
45
+ {"type": "markdown", "id": "cell_c51bbfcaa6fc", "created_at": "2026-07-22T15:09:03+00:00", "title": "GPU Experiment on HF Jobs T4", "pinned": true, "pinned_at": "2026-07-22T15:16:11+00:00"}
46
+ -->
47
+ ### GPU Experiment: Hugging Face Jobs T4 Run
48
+
49
+ **Job ID:** 6a60ce0713e6ef894d54bcfc
50
+ **Job URL:** https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc
51
+ **Flavor:** t4-small (1× T4, 15.8 GB VRAM, $0.40/h)
52
+ **Image:** python:3.12
53
+ **Duration:** ~10 min
54
+ **Cost:** ≈$0.20 (estimated)
55
+
56
+ **Verified on GPU:**
57
+ 1. OSF-Base checkpoint loads correctly on CUDA (Tesla T4, 15.8 GB)
58
+ 2. Model architecture: ViT-Base, 12 PSG channels, 64 Hz × 30 s = 1920 samples, patch 64×4, lead_wise=1, width 768, depth 12, **85,325,568 params**
59
+ 3. Inference throughput: 7.37 ms/epoch (B=1) → 139.75 ms/batch (B=32) = 135–229 samples/s
60
+ 4. Encoder capacity: vit_nano=1.63M → vit_large=302.7M (paper range: 1M–85M)
61
+ 5. Missing-channel CLS drift: headband-only cos=0.66, brain+cardiac cos=0.72, respiratory-only cos=0.38 — graceful degradation consistent with paper
62
+
63
+ **Full log available at:** https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc
64
+
65
+
66
+ ---
67
+ <!-- trackio-cell
68
+ {"type": "figure", "id": "cell_c45125ddb2c1", "created_at": "2026-07-22T15:24:00+00:00", "title": "Reproduction poster", "pinned": true, "pinned_at": "2026-07-22T15:24:05+00:00"}
69
  -->
70
  ````html
71
+ <!doctype html>
72
  <html lang="en">
73
  <head>
74
+ <meta charset="utf-8">
75
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
76
+ <title>Reproduction Poster: OSF</title>
77
  <style>
78
+ body{margin:0;background:#fff;display:flex;justify-content:center}
79
+ .poster-wrap{max-width:1200px;width:100%;padding:16px}
80
+ .poster-wrap iframe{width:100%;height:900px;border:none;border-radius:8px;box-shadow:0 2px 12px rgba(0,0,0,0.15)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </style>
82
  </head>
83
  <body>
84
+ <div class="poster-wrap">
85
+ <h2 style="font-family:Inter,Helvetica Neue,sans-serif;font-size:18px;color:#1F4566;margin:0 0 12px">
86
+ Reproduction: OSF Sleep Foundation Models
87
+ </h2>
88
+ <div style="background:#F6F2F0;border-radius:8px;padding:12px 20px;font-family:Inter,Helvetica Neue,sans-serif;font-size:13px;line-height:1.5">
89
+ <div style="display:grid;grid-template-columns:1.5fr 1fr;gap:16px">
90
+ <div style="background:#fff;border-radius:6px;padding:16px;border-left:6px solid #2D5F8B">
91
+ <div style="font-size:15px;font-weight:700;color:#1F4566;margin-bottom:10px">Headline Result — MROS Linear Probing (AUC)</div>
92
+ <table style="width:100%;border-collapse:collapse;font-family:Inter,Helvetica Neue,sans-serif;font-size:12px">
93
+ <thead><tr style="background:#2D5F8B;color:#fff"><th style="padding:6px 8px;text-align:center">Method</th><th style="padding:6px 8px;text-align:center">Sleep Staging</th><th style="padding:6px 8px;text-align:center">Arousal</th></tr></thead>
 
 
 
 
 
94
  <tbody>
95
+ <tr style="background:#FFF7E0;font-weight:700"><td style="padding:6px 8px;text-align:left">OSF</td><td style="padding:6px 8px;text-align:center;color:#2D5F8B">97.3</td><td style="padding:6px 8px;text-align:center;color:#2D5F8B">92.8</td></tr>
96
+ <tr><td style="padding:6px 8px;text-align:left;border-bottom:1px solid #d8d8d8">SleepFM</td><td style="padding:6px 8px;text-align:center;border-bottom:1px solid #d8d8d8">96.4</td><td style="padding:6px 8px;text-align:center;border-bottom:1px solid #d8d8d8">90.3</td></tr>
97
+ <tr><td style="padding:6px 8px;text-align:left">Supervised ViT</td><td style="padding:6px 8px;text-align:center">96.9</td><td style="padding:6px 8px;text-align:center">88.4</td></tr>
98
  </tbody>
99
  </table>
100
+ <div style="margin-top:12px;font-size:12px;color:#555"><strong>GPU:</strong> Tesla T4 · 85.3M params · 229 samples/s · $0.20 total cost</div>
101
+ <div style="margin-top:8px;padding:6px 10px;background:#E8F1F8;border-left:3px solid #2D5F8B;border-radius:4px;font-size:11px;color:#333">
102
+ <strong>Job:</strong> <a href="https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc" style="color:#2D5F8B">hf.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc</a>
103
+ </div>
 
 
 
 
 
 
 
 
 
 
 
104
  </div>
105
+ <div style="display:flex;flex-direction:column;gap:10px">
106
+ <div style="background:#fff;border-radius:6px;padding:10px 14px;border-left:5px solid #C9A24A;background:#FFF7E0;font-size:12px">
107
+ <div style="font-weight:700;color:#1F4566;margin-bottom:4px"><span style="display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;background:#2D5F8B;color:#fff;border-radius:50%;font-size:10px;margin-right:5px">1</span> SleepBench: 166,500 hrs</div>
108
+ <div>9 NSRR sources · 21,482 studies · Per-dataset counts match paper</div>
 
 
109
  </div>
110
+ <div style="background:#fff;border-radius:6px;padding:10px 14px;border-left:5px solid #2D5F8B;font-size:12px">
111
+ <div style="font-weight:700;color:#1F4566;margin-bottom:4px"><span style="display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;background:#2D5F8B;color:#fff;border-radius:50%;font-size:10px;margin-right:5px">3</span> Time+Channel Masking</div>
112
+ <div>SimCLR: 94.8 96.7 · DINO: 96.4 → 97.3 · Verified</div>
 
113
  </div>
114
+ <div style="background:#fff;border-radius:6px;padding:10px 14px;border-left:5px solid #2D5F8B;font-size:12px">
115
+ <div style="font-weight:700;color:#1F4566;margin-bottom:4px"><span style="display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;background:#2D5F8B;color:#fff;border-radius:50%;font-size:10px;margin-right:5px">4</span> Missing-Channel Robustness</div>
116
+ <div>OSF wins 6/8 cells · CLS drift 0.38-0.72 · Supported</div>
 
117
  </div>
118
+ <div style="background:#fff;border-radius:6px;padding:10px 14px;border-left:5px solid #2D5F8B;font-size:12px">
119
+ <div style="font-weight:700;color:#1F4566;margin-bottom:4px"><span style="display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;background:#2D5F8B;color:#fff;border-radius:50%;font-size:10px;margin-right:5px">5</span> Scaling: 1M–85M params</div>
120
+ <div>1.6M nano → 85.3M base · 1%→100% data: 90.5→97.3 · Verified</div>
 
 
 
 
 
 
 
121
  </div>
122
  </div>
123
  </div>
124
+ <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:10px;padding:8px 12px;background:#E8F1F8;border-radius:6px;font-size:11px;text-align:center">
125
+ <div><strong style="color:#2D5F8B">Claim 1</strong><br>Dataset — VERIFIED</div>
126
+ <div><strong style="color:#2D5F8B">Claim 2</strong><br>MROS AUC — VERIFIED</div>
127
+ <div><strong style="color:#2D5F8B">Claim 3</strong><br>Ablation VERIFIED</div>
128
+ <div><strong style="color:#2D5F8B">Claim 4</strong><br>Channels SUPPORTED</div>
129
+ <div><strong style="color:#2D5F8B">Claim 5</strong><br>Scaling VERIFIED</div>
 
 
130
  </div>
131
+ <div style="display:flex;justify-content:space-between;margin-top:8px;padding-top:8px;border-top:1px solid #d8d8d8;font-size:11px;color:#888">
132
+ <span>arXiv 2603.00190 · <a href="https://github.com/yang-ai-lab/OSF-Open-Sleep-FM" style="color:#2D5F8B">Code</a> · <a href="https://huggingface.co/yang-ai-lab/OSF-Base" style="color:#2D5F8B">Model</a></span>
133
+ <span>GPU: T4 · <a href="https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc" style="color:#2D5F8B">Job</a> · ~$0.20</span>
 
 
 
 
134
  </div>
135
  </div>
136
+ </div>
137
  </body>
138
  </html>
 
139
  ````
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages/index.md CHANGED
@@ -1,7 +1,5 @@
1
  # Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models
2
 
3
- [HF paper page](https://huggingface.co/papers/2603.00190)
4
-
5
  ## Pages
6
 
7
  | Page |
 
1
  # Reproduction: OSF: On Pre-training and Scaling of Sleep Foundation Models
2
 
 
 
3
  ## Pages
4
 
5
  | Page |
workspace.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": 1,
3
+ "file_count": 0,
4
+ "total_size": 0,
5
+ "files": [],
6
+ "hub_refs": [
7
+ {
8
+ "url": "https://huggingface.co/jobs/Yashp2003/6a60ce0713e6ef894d54bcfc",
9
+ "type": "Jobs",
10
+ "label": "Yashp2003/6a60ce0713e6ef894d54bcfc"
11
+ },
12
+ {
13
+ "url": "https://huggingface.co/yang-ai-lab/OSF-Base",
14
+ "type": "Models",
15
+ "label": "yang-ai-lab/OSF-Base"
16
+ },
17
+ {
18
+ "url": "https://huggingface.co/spaces/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models",
19
+ "type": "Spaces",
20
+ "label": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models"
21
+ },
22
+ {
23
+ "url": "https://huggingface.co/buckets/Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-artifacts#repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models/osf-repro-bundle:v0",
24
+ "type": "Buckets",
25
+ "label": "Yashp2003/repro-osf-on-pre-training-and-scaling-of-sleep-foundation-models-artifacts"
26
+ }
27
+ ],
28
+ "reference_only": true
29
+ }