Umong commited on
Commit
8ef07d7
·
verified ·
1 Parent(s): f620c09

Update logbook: Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs

Browse files
README.md CHANGED
@@ -1,10 +1,18 @@
1
  ---
2
- title: Repro Consistent Segmented Execution
3
- emoji: 🚀
4
- colorFrom: purple
5
  colorTo: red
6
  sdk: static
7
  pinned: false
 
 
 
 
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: "Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs"
3
+ emoji: 🎯
4
+ colorFrom: yellow
5
  colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - trackio
10
+ - trackio-logbook
11
+ - open-experiment
12
+ - icml2026-repro
13
+ - paper-PoRigyDOcC
14
  ---
15
 
16
+ # Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs
17
+
18
+ An open experiment logbook, published with [Trackio](https://github.com/gradio-app/trackio).
bucket-icon.svg ADDED
index.html CHANGED
@@ -1,19 +1,54 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs</title>
7
+ <link rel="stylesheet" href="./logbook.css" />
8
+ </head>
9
+ <body>
10
+ <div id="app">
11
+ <aside id="sidebar">
12
+ <div id="book-head">
13
+ <img id="book-wordmark" src="./trackio-wordmark-dark.png" alt="" />
14
+ <div id="book-title" class="sr-only">Logbook</div>
15
+ </div>
16
+ <nav id="tree"></nav>
17
+ <div id="sidebar-foot" hidden>
18
+ <button id="connect-btn" type="button">
19
+ <span class="ico">ⓘ</span> Collaborate with your agent
20
+ </button>
21
+ </div>
22
+ </aside>
23
+ <main id="content">
24
+ <div id="page"></div>
25
+ </main>
26
+ </div>
27
+
28
+ <div id="modal" hidden>
29
+ <div class="modal-backdrop"></div>
30
+ <div class="modal-card" role="dialog" aria-modal="true">
31
+ <div class="modal-head">
32
+ <div class="modal-title">
33
+ <img class="modal-logo" src="./trackio-logo.png" alt="" />
34
+ Collaborate with your agent
35
+ </div>
36
+ <div class="modal-actions">
37
+ <button id="copy-agent" class="btn">Copy for agent</button>
38
+ <button id="modal-close" class="btn icon" aria-label="Close">×</button>
39
+ </div>
40
+ </div>
41
+ <div class="modal-body">
42
+ <p class="modal-intro">
43
+ Point your coding agent at this logbook. It reads a compact,
44
+ token-efficient version — and if you've given it write access to this
45
+ Space, it can add findings that sync back automatically.
46
+ </p>
47
+ <ol id="connect-steps"></ol>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ <script src="./logbook.js"></script>
53
+ </body>
54
  </html>
logbook.css ADDED
@@ -0,0 +1,1602 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg: #ffffff;
3
+ --paper: #fdfcf9;
4
+ --panel: #ffffff;
5
+ --ink: #1f2937;
6
+ --muted: #6b7280;
7
+ --line: #e5e7eb;
8
+ --accent: #f97316;
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;
16
+ --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
17
+ sans-serif;
18
+ --mono: "SFMono-Regular", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas,
19
+ ui-monospace, monospace;
20
+ }
21
+
22
+ * {
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ html,
27
+ body {
28
+ margin: 0;
29
+ padding: 0;
30
+ }
31
+
32
+ html {
33
+ scroll-behavior: smooth;
34
+ }
35
+
36
+ body {
37
+ background: var(--bg);
38
+ color: var(--ink);
39
+ font-family: var(--sans);
40
+ font-size: 13px;
41
+ line-height: 1.65;
42
+ -webkit-font-smoothing: antialiased;
43
+ }
44
+
45
+ #app {
46
+ display: flex;
47
+ min-height: 100vh;
48
+ }
49
+
50
+ /* ---- sidebar (composition-book cover) ---- */
51
+ #sidebar {
52
+ width: 280px;
53
+ flex: 0 0 280px;
54
+ background: #17181c;
55
+ color: #e7e7ea;
56
+ position: sticky;
57
+ top: 0;
58
+ height: 100vh;
59
+ overflow-y: auto;
60
+ padding: 22px 16px;
61
+ display: flex;
62
+ flex-direction: column;
63
+ }
64
+
65
+ #book-head {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 10px;
69
+ padding: 8px;
70
+ margin-bottom: 12px;
71
+ border-radius: 10px;
72
+ cursor: pointer;
73
+ transition: background 0.12s;
74
+ }
75
+ #book-head:hover {
76
+ background: rgba(255, 255, 255, 0.05);
77
+ }
78
+ #book-wordmark {
79
+ width: 154px;
80
+ height: auto;
81
+ object-fit: contain;
82
+ }
83
+ .sr-only {
84
+ position: absolute;
85
+ width: 1px;
86
+ height: 1px;
87
+ padding: 0;
88
+ margin: -1px;
89
+ overflow: hidden;
90
+ clip: rect(0, 0, 0, 0);
91
+ white-space: nowrap;
92
+ border: 0;
93
+ }
94
+
95
+ #tree {
96
+ flex: 1;
97
+ padding-top: 8px;
98
+ }
99
+
100
+ #tree a {
101
+ display: block;
102
+ padding: 6px 10px;
103
+ border-radius: 8px;
104
+ color: #c3c4cb;
105
+ text-decoration: none;
106
+ font-size: 14px;
107
+ transition: background 0.12s, color 0.12s;
108
+ }
109
+
110
+ #tree a:hover {
111
+ background: rgba(255, 255, 255, 0.06);
112
+ color: #ffffff;
113
+ }
114
+
115
+ #tree a.active {
116
+ background: rgba(249, 115, 22, 0.16);
117
+ color: #fdba74;
118
+ font-weight: 600;
119
+ }
120
+
121
+ #tree a .tree-mark {
122
+ color: #6b6d76;
123
+ }
124
+
125
+ #tree a:hover .tree-mark,
126
+ #tree a.active .tree-mark {
127
+ color: inherit;
128
+ opacity: 0.6;
129
+ }
130
+
131
+ #tree .depth-1 {
132
+ padding-left: 22px;
133
+ }
134
+ #tree .depth-2 {
135
+ padding-left: 34px;
136
+ }
137
+ #tree .depth-3 {
138
+ padding-left: 46px;
139
+ }
140
+
141
+
142
+ /* ---- content ---- */
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),
150
+ linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
151
+ background-size: 26px 26px;
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
+
162
+ .page-section {
163
+ scroll-margin-top: 40px;
164
+ padding: 0 0 35px;
165
+ margin: 0 0 32px;
166
+ }
167
+
168
+ .page-section:last-child {
169
+ margin-bottom: 0;
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 {
180
+ min-width: 0;
181
+ }
182
+
183
+ .resource-anchor {
184
+ display: block;
185
+ height: 0;
186
+ overflow: hidden;
187
+ }
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;
206
+ margin-bottom: 30px;
207
+ }
208
+ .book-intro.book-intro-tight {
209
+ border-bottom: none;
210
+ padding-bottom: 4px;
211
+ margin-bottom: 20px;
212
+ }
213
+
214
+ #page h1 {
215
+ font-family: var(--serif);
216
+ font-size: 34px;
217
+ line-height: 1.15;
218
+ letter-spacing: -0.02em;
219
+ margin: 0 0 8px;
220
+ overflow-wrap: anywhere;
221
+ }
222
+
223
+ #page .page-section:not(.book-intro) h1 {
224
+ font-size: 26px;
225
+ }
226
+
227
+ #page h2 {
228
+ font-family: var(--serif);
229
+ font-size: 24px;
230
+ margin: 36px 0 10px;
231
+ }
232
+
233
+ #page h3 {
234
+ font-size: 17px;
235
+ font-weight: 700;
236
+ margin: 26px 0 2px;
237
+ letter-spacing: -0.01em;
238
+ }
239
+
240
+ #page h3::before {
241
+ content: "";
242
+ display: inline-block;
243
+ width: 7px;
244
+ height: 7px;
245
+ border-radius: 2px;
246
+ background: var(--accent);
247
+ margin-right: 10px;
248
+ vertical-align: middle;
249
+ transform: translateY(-1px);
250
+ }
251
+
252
+ #page p {
253
+ margin: 10px 0;
254
+ }
255
+
256
+ #page blockquote {
257
+ margin: 14px 0;
258
+ padding: 2px 16px;
259
+ border-left: 3px solid #fdba74;
260
+ color: var(--muted);
261
+ }
262
+
263
+ #page hr {
264
+ display: none;
265
+ }
266
+
267
+ #page code {
268
+ font-family: var(--mono);
269
+ font-size: 0.86em;
270
+ background: var(--code-bg);
271
+ padding: 2px 6px;
272
+ border-radius: 6px;
273
+ }
274
+
275
+ #page pre {
276
+ max-width: 100%;
277
+ background: var(--code-bg);
278
+ border: 1px solid var(--line);
279
+ border-radius: var(--radius);
280
+ padding: 14px 16px;
281
+ overflow-x: auto;
282
+ }
283
+ #page pre code {
284
+ background: none;
285
+ padding: 0;
286
+ font-size: 11.5px;
287
+ }
288
+
289
+ /* ---- code blocks + collapsible accordion ---- */
290
+ #page pre.hl {
291
+ background: #17181c;
292
+ border: none;
293
+ color: #e7e7ea;
294
+ font-size: 13px;
295
+ line-height: 1.58;
296
+ }
297
+ #page pre.hl code {
298
+ color: inherit;
299
+ font-family: var(--mono);
300
+ }
301
+ .code-accordion {
302
+ border: 1px solid rgba(249, 115, 22, 0.2);
303
+ border-radius: 8px;
304
+ overflow: hidden;
305
+ margin: 12px 0;
306
+ background: #17181c;
307
+ }
308
+ .code-accordion summary {
309
+ list-style: none;
310
+ cursor: pointer;
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 9px;
314
+ padding: 9px 12px;
315
+ font-family: var(--mono);
316
+ font-size: 11.5px;
317
+ font-weight: 700;
318
+ color: #e7e7ea;
319
+ background: #1e2027;
320
+ user-select: none;
321
+ overflow-wrap: anywhere;
322
+ }
323
+ .code-accordion summary::-webkit-details-marker {
324
+ display: none;
325
+ }
326
+ .code-accordion summary::after {
327
+ content: "▸";
328
+ margin-left: auto;
329
+ color: var(--accent);
330
+ transition: transform 0.12s;
331
+ transform: rotate(180deg);
332
+ }
333
+ .code-accordion[open] summary::after {
334
+ transform: rotate(90deg);
335
+ }
336
+ .code-accordion .code-ico {
337
+ color: var(--accent);
338
+ font-weight: 700;
339
+ }
340
+ .code-accordion pre.hl {
341
+ margin: 0;
342
+ border-radius: 0;
343
+ border: none;
344
+ border-top: 1px solid rgba(249, 115, 22, 0.16);
345
+ }
346
+ .tok-comment {
347
+ color: #7a7d87;
348
+ font-style: italic;
349
+ }
350
+ .tok-string {
351
+ color: #a5d6a7;
352
+ }
353
+ .tok-keyword {
354
+ color: #fdba74;
355
+ }
356
+ .tok-number {
357
+ color: #7fd0e0;
358
+ }
359
+
360
+ #page a {
361
+ color: var(--accent);
362
+ }
363
+
364
+ #page ul {
365
+ padding-left: 20px;
366
+ }
367
+
368
+ .ts {
369
+ font-family: var(--mono);
370
+ font-size: 12px;
371
+ color: var(--muted);
372
+ background: none;
373
+ padding: 0;
374
+ }
375
+
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;
402
+ min-width: 0;
403
+ font-size: 13px;
404
+ font-weight: 650;
405
+ color: var(--ink);
406
+ line-height: 1.35;
407
+ overflow-wrap: anywhere;
408
+ }
409
+ .cell-meta {
410
+ flex: 0 0 auto;
411
+ display: flex;
412
+ align-items: center;
413
+ gap: 10px;
414
+ font-family: var(--sans);
415
+ font-size: 13px;
416
+ color: var(--muted);
417
+ }
418
+ .cell-open {
419
+ flex: 0 0 auto;
420
+ font-family: var(--mono);
421
+ font-size: 12px;
422
+ color: var(--accent);
423
+ text-decoration: none;
424
+ }
425
+ .cell-open:hover {
426
+ color: var(--accent-strong);
427
+ }
428
+ .cell-body {
429
+ min-width: 0;
430
+ padding: 14px 18px 18px;
431
+ }
432
+ .cell.dashboard .cell-body {
433
+ padding: 0;
434
+ }
435
+ #page .cell-body h1,
436
+ #page .cell-body h2 {
437
+ font-family: var(--sans);
438
+ font-size: 17px;
439
+ font-weight: 700;
440
+ letter-spacing: -0.01em;
441
+ line-height: 1.35;
442
+ margin: 22px 0 6px;
443
+ }
444
+ #page .cell-body > :first-child {
445
+ margin-top: 0;
446
+ }
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;
456
+ min-height: 160px;
457
+ border: 1px solid var(--line);
458
+ border-radius: 8px;
459
+ background: #fff;
460
+ }
461
+ .figure-fit[hidden] {
462
+ display: none;
463
+ }
464
+ .figure-fit:fullscreen,
465
+ .figure-fit:-webkit-full-screen {
466
+ width: 100%;
467
+ height: 100%;
468
+ border: none;
469
+ border-radius: 0;
470
+ }
471
+ .figure-frame {
472
+ display: block;
473
+ width: 100%;
474
+ min-height: 160px;
475
+ border: none;
476
+ background: #fff;
477
+ }
478
+ .figure-frame[hidden],
479
+ .figure-raw[hidden] {
480
+ display: none;
481
+ }
482
+ .fig-switch {
483
+ position: relative;
484
+ display: inline-flex;
485
+ flex: 0 0 auto;
486
+ border: 1px solid var(--line);
487
+ border-radius: 999px;
488
+ background: var(--code-bg);
489
+ padding: 2px;
490
+ }
491
+ .fig-switch button {
492
+ position: relative;
493
+ z-index: 1;
494
+ flex: 1;
495
+ min-width: 62px;
496
+ border: none;
497
+ background: none;
498
+ font-family: var(--sans);
499
+ font-size: 12px;
500
+ font-weight: 600;
501
+ color: var(--muted);
502
+ padding: 3px 12px;
503
+ border-radius: 999px;
504
+ cursor: pointer;
505
+ transition: color 0.15s;
506
+ }
507
+ .fig-switch button.active {
508
+ color: var(--accent-strong);
509
+ }
510
+ .fig-switch-thumb {
511
+ position: absolute;
512
+ top: 2px;
513
+ bottom: 2px;
514
+ left: 2px;
515
+ width: calc(50% - 2px);
516
+ border-radius: 999px;
517
+ background: var(--panel);
518
+ border: 1px solid rgba(249, 115, 22, 0.35);
519
+ box-shadow: 0 1px 4px rgba(31, 41, 55, 0.08);
520
+ transition: transform 0.18s ease;
521
+ }
522
+ .fig-switch.raw .fig-switch-thumb {
523
+ transform: translateX(100%);
524
+ }
525
+ #page .figure-raw pre {
526
+ margin: 0;
527
+ max-height: 420px;
528
+ overflow: auto;
529
+ font-family: var(--mono);
530
+ font-size: 13px;
531
+ line-height: 1.55;
532
+ background: var(--code-bg);
533
+ border: 1px solid var(--line);
534
+ border-radius: 8px;
535
+ padding: 12px 14px;
536
+ }
537
+ /* ---- figure fullscreen ---- */
538
+ .cell-fullscreen {
539
+ position: relative;
540
+ display: inline-flex;
541
+ flex: 0 0 auto;
542
+ }
543
+ .cell-fullscreen-btn {
544
+ display: inline-flex;
545
+ align-items: center;
546
+ justify-content: center;
547
+ width: 26px;
548
+ height: 26px;
549
+ padding: 0;
550
+ border: 1px solid var(--line);
551
+ border-radius: 999px;
552
+ background: var(--code-bg);
553
+ color: var(--muted);
554
+ cursor: pointer;
555
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
556
+ }
557
+ .cell-fullscreen-btn:hover {
558
+ color: var(--accent-strong);
559
+ border-color: rgba(249, 115, 22, 0.35);
560
+ background: var(--accent-soft);
561
+ }
562
+ .cell-fullscreen-btn svg {
563
+ width: 14px;
564
+ height: 14px;
565
+ }
566
+ /* ---- copyable snippets ---- */
567
+ .snippet {
568
+ position: relative;
569
+ }
570
+ .copy-snippet {
571
+ position: absolute;
572
+ top: 7px;
573
+ right: 8px;
574
+ width: 24px;
575
+ height: 24px;
576
+ border: none;
577
+ border-radius: 6px;
578
+ background: rgba(255, 255, 255, 0.08);
579
+ color: #9a9da8;
580
+ font-size: 12px;
581
+ line-height: 1;
582
+ cursor: pointer;
583
+ opacity: 0;
584
+ transition: opacity 0.12s, color 0.12s, background 0.12s;
585
+ }
586
+ .snippet:hover .copy-snippet,
587
+ .jp-out:hover .copy-snippet,
588
+ .figure-raw:hover .copy-snippet,
589
+ .code-accordion summary:hover .copy-snippet {
590
+ opacity: 1;
591
+ }
592
+ .copy-snippet:hover {
593
+ color: #ffffff;
594
+ background: rgba(255, 255, 255, 0.16);
595
+ }
596
+ .copy-snippet.copied {
597
+ color: #52d08a;
598
+ opacity: 1;
599
+ }
600
+ .code-accordion .code-name {
601
+ user-select: text;
602
+ cursor: text;
603
+ }
604
+ .jp-out,
605
+ .figure-raw {
606
+ position: relative;
607
+ }
608
+ .jp-out .copy-snippet,
609
+ .figure-raw .copy-snippet {
610
+ background: var(--code-bg);
611
+ color: var(--muted);
612
+ border: 1px solid var(--line);
613
+ }
614
+ .jp-out .copy-snippet:hover,
615
+ .figure-raw .copy-snippet:hover {
616
+ color: var(--accent-strong);
617
+ background: var(--panel);
618
+ }
619
+
620
+ /* ---- jupyter-style code cells ---- */
621
+ .jp {
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;
631
+ font-family: var(--mono);
632
+ font-size: 10.5px;
633
+ letter-spacing: 0.07em;
634
+ text-transform: uppercase;
635
+ font-weight: 600;
636
+ user-select: none;
637
+ }
638
+ .jp-in {
639
+ display: flex;
640
+ background: #17181c;
641
+ }
642
+ .jp-in .jp-gutter {
643
+ color: #6f727d;
644
+ }
645
+ .jp-in-body {
646
+ flex: 1;
647
+ min-width: 0;
648
+ }
649
+ #page .jp-in-body pre.hl {
650
+ margin: 0;
651
+ border: none;
652
+ border-radius: 0;
653
+ background: none;
654
+ padding: 12px 16px 12px 0;
655
+ }
656
+ .jp-in-body .code-accordion {
657
+ margin: 0;
658
+ border: none;
659
+ border-top: 1px solid rgba(255, 255, 255, 0.09);
660
+ border-radius: 0;
661
+ background: none;
662
+ }
663
+ .jp-in-body .code-accordion summary {
664
+ background: none;
665
+ padding: 9px 16px 9px 0;
666
+ }
667
+ .jp-in-body .code-accordion pre.hl {
668
+ border-top: 1px solid rgba(255, 255, 255, 0.09);
669
+ }
670
+ .jp-meta {
671
+ padding: 5px 14px;
672
+ font-family: var(--mono);
673
+ font-size: 11.5px;
674
+ color: var(--muted);
675
+ background: #fbfbfc;
676
+ border-top: 1px solid var(--line);
677
+ }
678
+ .jp-out {
679
+ display: flex;
680
+ border-top: 1px solid var(--line);
681
+ background: var(--panel);
682
+ }
683
+ .jp-out .jp-gutter {
684
+ color: var(--accent-strong);
685
+ }
686
+ .jp-out-body {
687
+ flex: 1;
688
+ min-width: 0;
689
+ }
690
+ #page .jp-out-pre {
691
+ min-width: 0;
692
+ margin: 0;
693
+ border: none;
694
+ border-radius: 0;
695
+ background: none;
696
+ color: var(--ink);
697
+ font-family: var(--mono);
698
+ font-size: 13px;
699
+ line-height: 1.55;
700
+ padding: 12px 16px 12px 0;
701
+ white-space: pre;
702
+ overflow-x: auto;
703
+ overflow-y: auto;
704
+ max-height: 26em;
705
+ }
706
+ .jp-artifacts {
707
+ display: flex;
708
+ flex-direction: column;
709
+ }
710
+ .jp-out-body .jp-out-pre + .jp-artifacts {
711
+ border-top: 1px solid var(--line);
712
+ }
713
+ .out-artifact {
714
+ display: flex;
715
+ align-items: baseline;
716
+ gap: 8px;
717
+ padding: 9px 16px 9px 0;
718
+ text-decoration: none;
719
+ color: inherit;
720
+ }
721
+ .out-artifact + .out-artifact {
722
+ border-top: 1px solid var(--line);
723
+ }
724
+ a.out-artifact:hover .out-artifact-name {
725
+ color: var(--accent-strong);
726
+ }
727
+ .out-artifact-ico {
728
+ flex: 0 0 auto;
729
+ font-size: 13px;
730
+ }
731
+ .out-artifact-name {
732
+ font-family: var(--mono);
733
+ font-size: 12.5px;
734
+ font-weight: 600;
735
+ color: var(--ink);
736
+ overflow: hidden;
737
+ text-overflow: ellipsis;
738
+ white-space: nowrap;
739
+ }
740
+ .out-artifact-meta {
741
+ flex: 0 0 auto;
742
+ margin-left: auto;
743
+ padding-left: 12px;
744
+ font-size: 12px;
745
+ color: var(--muted);
746
+ white-space: nowrap;
747
+ }
748
+ .out-artifact-state.open {
749
+ color: var(--accent);
750
+ font-weight: 600;
751
+ }
752
+ .trackio-embed {
753
+ border: 1px solid var(--line);
754
+ border-radius: var(--radius);
755
+ overflow: hidden;
756
+ background: var(--panel);
757
+ }
758
+ .trackio-cell-meta {
759
+ display: flex;
760
+ gap: 6px;
761
+ flex-wrap: wrap;
762
+ justify-content: flex-end;
763
+ }
764
+
765
+ /* ---- unfurl cards ---- */
766
+ .unfurl {
767
+ display: block;
768
+ border: 1px solid var(--line);
769
+ border-radius: var(--radius);
770
+ background: var(--panel);
771
+ margin: 12px 0;
772
+ overflow: hidden;
773
+ text-decoration: none;
774
+ color: inherit;
775
+ transition: border-color 0.14s, box-shadow 0.14s;
776
+ }
777
+ .unfurl:hover {
778
+ border-color: #cfcbe6;
779
+ box-shadow: 0 4px 18px rgba(30, 20, 80, 0.06);
780
+ }
781
+
782
+ .unfurl-body {
783
+ padding: 13px 16px;
784
+ display: flex;
785
+ gap: 12px;
786
+ align-items: flex-start;
787
+ }
788
+
789
+ .unfurl-ico {
790
+ font-size: 20px;
791
+ line-height: 1.3;
792
+ flex: 0 0 auto;
793
+ }
794
+
795
+ .unfurl-main {
796
+ min-width: 0;
797
+ flex: 1;
798
+ }
799
+
800
+ .unfurl-kind {
801
+ font-family: var(--mono);
802
+ font-size: 10.5px;
803
+ text-transform: uppercase;
804
+ letter-spacing: 0.08em;
805
+ color: var(--accent);
806
+ font-weight: 600;
807
+ }
808
+
809
+ .unfurl-title {
810
+ font-weight: 650;
811
+ font-size: 15px;
812
+ margin: 1px 0 2px;
813
+ white-space: nowrap;
814
+ overflow: hidden;
815
+ text-overflow: ellipsis;
816
+ }
817
+
818
+ .unfurl-desc {
819
+ color: var(--muted);
820
+ font-size: 13.5px;
821
+ line-height: 1.45;
822
+ }
823
+
824
+ .unfurl-meta {
825
+ margin-top: 6px;
826
+ display: flex;
827
+ flex-wrap: wrap;
828
+ gap: 6px;
829
+ }
830
+
831
+ .chip {
832
+ font-size: 11.5px;
833
+ background: var(--code-bg);
834
+ border-radius: 999px;
835
+ padding: 2px 9px;
836
+ color: var(--muted);
837
+ font-family: var(--mono);
838
+ }
839
+
840
+ .unfurl-raw {
841
+ font-family: var(--mono);
842
+ font-size: 11px;
843
+ color: var(--muted);
844
+ border-top: 1px solid var(--line);
845
+ padding: 7px 16px;
846
+ white-space: nowrap;
847
+ overflow: hidden;
848
+ text-overflow: ellipsis;
849
+ }
850
+
851
+ .unfurl.embed {
852
+ padding: 0;
853
+ overflow: hidden;
854
+ }
855
+ .embed-head {
856
+ display: flex;
857
+ align-items: center;
858
+ gap: 10px;
859
+ padding: 10px 14px;
860
+ border-bottom: 1px solid var(--line);
861
+ }
862
+ .embed-head .unfurl-kind {
863
+ flex: 0 0 auto;
864
+ }
865
+ .embed-title {
866
+ flex: 1;
867
+ min-width: 0;
868
+ font-weight: 650;
869
+ font-size: 14px;
870
+ color: var(--ink);
871
+ text-decoration: none;
872
+ white-space: nowrap;
873
+ overflow: hidden;
874
+ text-overflow: ellipsis;
875
+ }
876
+ .embed-title:hover {
877
+ color: var(--accent);
878
+ }
879
+ .embed-open {
880
+ flex: 0 0 auto;
881
+ font-family: var(--mono);
882
+ font-size: 12px;
883
+ color: var(--accent);
884
+ text-decoration: none;
885
+ }
886
+ .embed-frame {
887
+ display: block;
888
+ width: 100%;
889
+ height: 560px;
890
+ border: 0;
891
+ background: var(--code-bg);
892
+ }
893
+
894
+ .dashboard-shell {
895
+ display: block;
896
+ }
897
+ .dashboard-shell .dashboard-frame {
898
+ display: block;
899
+ width: 100%;
900
+ height: 900px;
901
+ border: 0;
902
+ background: var(--code-bg);
903
+ }
904
+
905
+ .unfurl.image {
906
+ padding: 0;
907
+ }
908
+ .unfurl.image img {
909
+ display: block;
910
+ width: 100%;
911
+ height: auto;
912
+ max-height: 460px;
913
+ object-fit: contain;
914
+ background: var(--code-bg);
915
+ }
916
+
917
+ .artifact-chip {
918
+ border: 1px solid var(--line);
919
+ background: var(--panel);
920
+ border-radius: var(--radius);
921
+ padding: 10px 14px;
922
+ margin: 8px 0;
923
+ font-size: 14px;
924
+ }
925
+ .cell.dashboard .artifact-chip {
926
+ margin: 14px 18px 18px;
927
+ }
928
+ .artifact-chip code {
929
+ color: var(--accent);
930
+ }
931
+
932
+ /* ---- task board ---- */
933
+ .board-wrap {
934
+ overflow-x: auto;
935
+ border: 1px solid var(--line);
936
+ border-radius: var(--radius);
937
+ margin: 12px 0 20px;
938
+ background: var(--panel);
939
+ }
940
+ table.board {
941
+ border-collapse: collapse;
942
+ width: 100%;
943
+ font-size: 14px;
944
+ }
945
+ table.board th,
946
+ table.board td {
947
+ text-align: left;
948
+ padding: 9px 14px;
949
+ border-bottom: 1px solid var(--line);
950
+ vertical-align: top;
951
+ }
952
+ table.board thead th {
953
+ background: var(--accent-soft);
954
+ font-size: 12px;
955
+ text-transform: uppercase;
956
+ letter-spacing: 0.05em;
957
+ color: #9a4a12;
958
+ font-weight: 600;
959
+ border-bottom: 1px solid var(--line);
960
+ }
961
+ table.board tbody tr:last-child td {
962
+ border-bottom: none;
963
+ }
964
+ table.board .col-check {
965
+ text-align: center;
966
+ width: 92px;
967
+ white-space: nowrap;
968
+ }
969
+ table.board tr.section-row td {
970
+ background: var(--accent-soft);
971
+ text-align: center;
972
+ font-weight: 700;
973
+ font-size: 13px;
974
+ color: var(--accent-strong);
975
+ padding: 7px 14px;
976
+ letter-spacing: 0.02em;
977
+ }
978
+ .box {
979
+ display: inline-flex;
980
+ align-items: center;
981
+ justify-content: center;
982
+ width: 18px;
983
+ height: 18px;
984
+ border: 1.5px solid #cfcbe0;
985
+ border-radius: 5px;
986
+ font-size: 12px;
987
+ color: #fff;
988
+ line-height: 1;
989
+ }
990
+ .box.on {
991
+ background: var(--accent);
992
+ border-color: var(--accent);
993
+ }
994
+ .who-chip {
995
+ display: inline-block;
996
+ padding: 3px 12px;
997
+ border-radius: 999px;
998
+ font-size: 12.5px;
999
+ font-weight: 600;
1000
+ white-space: nowrap;
1001
+ }
1002
+ .who-chip.muted {
1003
+ background: var(--code-bg);
1004
+ color: var(--muted);
1005
+ font-weight: 500;
1006
+ }
1007
+
1008
+ /* ---- status badges + clickable rows ---- */
1009
+ table.board .col-status {
1010
+ width: 130px;
1011
+ white-space: nowrap;
1012
+ }
1013
+ .badge {
1014
+ display: inline-block;
1015
+ padding: 3px 11px;
1016
+ border-radius: 999px;
1017
+ font-size: 12px;
1018
+ font-weight: 600;
1019
+ letter-spacing: 0.01em;
1020
+ }
1021
+ .badge.gray {
1022
+ background: var(--code-bg);
1023
+ color: var(--muted);
1024
+ }
1025
+ .badge.amber {
1026
+ background: var(--accent-soft);
1027
+ color: #b45309;
1028
+ }
1029
+ .badge.green {
1030
+ background: #e6f7ee;
1031
+ color: #1a8a55;
1032
+ }
1033
+ .badge.red {
1034
+ background: #fde8ec;
1035
+ color: #c62a4b;
1036
+ }
1037
+ table.board tr.linked-row {
1038
+ cursor: pointer;
1039
+ }
1040
+ table.board tr.linked-row:hover td {
1041
+ background: var(--accent-soft);
1042
+ }
1043
+ table.board tr.linked-row a {
1044
+ color: var(--ink);
1045
+ font-weight: 600;
1046
+ text-decoration: none;
1047
+ }
1048
+ table.board tr.linked-row:hover a {
1049
+ color: var(--accent-strong);
1050
+ }
1051
+
1052
+ /* ---- agent read hint ---- */
1053
+ .agent-hint {
1054
+ display: flex;
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;
1066
+ font-family: var(--mono);
1067
+ font-size: 12px;
1068
+ font-weight: 500;
1069
+ color: var(--ink);
1070
+ }
1071
+ .agent-hint .copy {
1072
+ flex: 0 0 auto;
1073
+ background: none;
1074
+ color: var(--muted);
1075
+ border: 1px solid var(--line);
1076
+ border-radius: 6px;
1077
+ width: 22px;
1078
+ height: 22px;
1079
+ font-size: 11px;
1080
+ line-height: 1;
1081
+ cursor: pointer;
1082
+ transition: color 0.12s, border-color 0.12s;
1083
+ }
1084
+ .agent-hint .copy:hover {
1085
+ color: var(--accent-strong);
1086
+ border-color: var(--accent);
1087
+ }
1088
+ .agent-hint .copy.copied {
1089
+ color: #1a8a55;
1090
+ border-color: #1a8a55;
1091
+ }
1092
+ .agent-hint-note {
1093
+ margin-left: auto;
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;
1249
+ height: 1em;
1250
+ object-fit: contain;
1251
+ vertical-align: -0.15em;
1252
+ }
1253
+
1254
+ /* ---- scroll-to-resource highlight ---- */
1255
+ .res-flash {
1256
+ animation: res-flash 1.5s ease;
1257
+ border-radius: 8px;
1258
+ }
1259
+ @keyframes res-flash {
1260
+ 0%,
1261
+ 25% {
1262
+ box-shadow: 0 0 0 3px var(--accent);
1263
+ }
1264
+ 100% {
1265
+ box-shadow: 0 0 0 3px rgba(249, 115, 22, 0);
1266
+ }
1267
+ }
1268
+
1269
+ /* ---- inline resource chips ---- */
1270
+ #page .res-chip {
1271
+ display: inline-flex;
1272
+ align-items: center;
1273
+ gap: 5px;
1274
+ max-width: 100%;
1275
+ padding: 0 9px 0 6px;
1276
+ margin: 0 1px;
1277
+ border: 1px solid var(--line);
1278
+ border-radius: 999px;
1279
+ background: var(--panel);
1280
+ font-family: var(--mono);
1281
+ font-size: 0.78em;
1282
+ font-weight: 600;
1283
+ color: var(--ink);
1284
+ text-decoration: none;
1285
+ white-space: nowrap;
1286
+ overflow: hidden;
1287
+ text-overflow: ellipsis;
1288
+ vertical-align: middle;
1289
+ line-height: 1.65;
1290
+ transform: translateY(-0.08em);
1291
+ transition: border-color 0.12s, background 0.12s, color 0.12s;
1292
+ }
1293
+ .res-chip-ico {
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 {
1402
+ margin-top: auto;
1403
+ padding-top: 14px;
1404
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
1405
+ }
1406
+
1407
+ #connect-btn {
1408
+ width: 100%;
1409
+ display: flex;
1410
+ align-items: center;
1411
+ gap: 8px;
1412
+ background: rgba(255, 255, 255, 0.05);
1413
+ color: #c3c4cb;
1414
+ border: 1px solid rgba(255, 255, 255, 0.12);
1415
+ border-radius: 9px;
1416
+ padding: 9px 12px;
1417
+ font-size: 13.5px;
1418
+ font-family: var(--sans);
1419
+ cursor: pointer;
1420
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
1421
+ }
1422
+ #connect-btn:hover {
1423
+ background: rgba(249, 115, 22, 0.14);
1424
+ border-color: rgba(249, 115, 22, 0.4);
1425
+ color: #fdba74;
1426
+ }
1427
+ #connect-btn .ico {
1428
+ font-size: 15px;
1429
+ }
1430
+
1431
+ #modal[hidden] {
1432
+ display: none;
1433
+ }
1434
+ #modal {
1435
+ position: fixed;
1436
+ inset: 0;
1437
+ z-index: 100;
1438
+ display: flex;
1439
+ align-items: center;
1440
+ justify-content: center;
1441
+ padding: 24px;
1442
+ }
1443
+ .modal-backdrop {
1444
+ position: absolute;
1445
+ inset: 0;
1446
+ background: rgba(20, 18, 30, 0.5);
1447
+ backdrop-filter: blur(2px);
1448
+ }
1449
+ .modal-card {
1450
+ position: relative;
1451
+ background: var(--panel);
1452
+ border-radius: 16px;
1453
+ width: 100%;
1454
+ max-width: 620px;
1455
+ max-height: 85vh;
1456
+ overflow-y: auto;
1457
+ box-shadow: 0 24px 70px rgba(20, 15, 50, 0.28);
1458
+ }
1459
+ .modal-head {
1460
+ display: flex;
1461
+ align-items: center;
1462
+ justify-content: space-between;
1463
+ gap: 12px;
1464
+ padding: 18px 22px;
1465
+ border-bottom: 1px solid var(--line);
1466
+ position: sticky;
1467
+ top: 0;
1468
+ background: var(--panel);
1469
+ }
1470
+ .modal-title {
1471
+ display: flex;
1472
+ align-items: center;
1473
+ gap: 10px;
1474
+ font-family: var(--serif);
1475
+ font-size: 21px;
1476
+ letter-spacing: -0.01em;
1477
+ }
1478
+ .modal-logo {
1479
+ width: 26px;
1480
+ height: 26px;
1481
+ object-fit: contain;
1482
+ }
1483
+ .modal-actions {
1484
+ display: flex;
1485
+ align-items: center;
1486
+ gap: 8px;
1487
+ }
1488
+ .btn {
1489
+ font-family: var(--sans);
1490
+ font-size: 13.5px;
1491
+ font-weight: 600;
1492
+ border: 1px solid var(--line);
1493
+ background: var(--panel);
1494
+ color: var(--ink);
1495
+ border-radius: 9px;
1496
+ padding: 8px 13px;
1497
+ cursor: pointer;
1498
+ transition: background 0.12s, border-color 0.12s, color 0.12s;
1499
+ }
1500
+ .btn:hover {
1501
+ border-color: var(--accent);
1502
+ color: var(--accent-strong);
1503
+ }
1504
+ .btn.copied {
1505
+ border-color: #1a8a55;
1506
+ color: #1a8a55;
1507
+ }
1508
+ .btn.icon {
1509
+ font-size: 18px;
1510
+ line-height: 1;
1511
+ padding: 6px 11px;
1512
+ font-weight: 400;
1513
+ }
1514
+ .modal-body {
1515
+ padding: 20px 22px 26px;
1516
+ }
1517
+ .modal-intro {
1518
+ margin: 0 0 20px;
1519
+ color: var(--muted);
1520
+ line-height: 1.55;
1521
+ }
1522
+ #connect-steps {
1523
+ list-style: none;
1524
+ margin: 0;
1525
+ padding: 0;
1526
+ }
1527
+ #connect-steps li {
1528
+ margin-bottom: 18px;
1529
+ }
1530
+ .step-title {
1531
+ font-weight: 600;
1532
+ font-size: 14.5px;
1533
+ margin-bottom: 8px;
1534
+ }
1535
+ .codeblock {
1536
+ display: flex;
1537
+ align-items: center;
1538
+ gap: 8px;
1539
+ background: #17181c;
1540
+ border-radius: 10px;
1541
+ padding: 11px 12px 11px 15px;
1542
+ }
1543
+ .codeblock code {
1544
+ flex: 1;
1545
+ min-width: 0;
1546
+ overflow-x: auto;
1547
+ white-space: nowrap;
1548
+ font-family: var(--mono);
1549
+ font-size: 13px;
1550
+ color: #f0efff;
1551
+ background: none;
1552
+ padding: 0;
1553
+ }
1554
+ .codeblock .copy {
1555
+ flex: 0 0 auto;
1556
+ background: rgba(255, 255, 255, 0.08);
1557
+ color: #c3c4cb;
1558
+ border: 1px solid rgba(255, 255, 255, 0.14);
1559
+ border-radius: 7px;
1560
+ width: 30px;
1561
+ height: 30px;
1562
+ font-size: 14px;
1563
+ cursor: pointer;
1564
+ transition: background 0.12s, color 0.12s;
1565
+ }
1566
+ .codeblock .copy:hover {
1567
+ background: rgba(249, 115, 22, 0.2);
1568
+ color: #fdba74;
1569
+ }
1570
+ .codeblock .copy.copied {
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 {
1598
+ align-items: flex-start;
1599
+ flex-direction: column;
1600
+ gap: 4px;
1601
+ }
1602
+ }
logbook.js ADDED
@@ -0,0 +1,2275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function () {
2
+ "use strict";
3
+
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)
13
+ .replace(/&/g, "&amp;")
14
+ .replace(/</g, "&lt;")
15
+ .replace(/>/g, "&gt;")
16
+ .replace(/"/g, "&quot;")
17
+ .replace(/'/g, "&#39;");
18
+ }
19
+
20
+ function flattenTree(node, depth, acc) {
21
+ acc.push({ node: node, depth: depth });
22
+ (node.children || []).forEach((c) => flattenTree(c, depth + 1, acc));
23
+ return acc;
24
+ }
25
+
26
+ function findNode(node, slug) {
27
+ if (node.slug === slug) return node;
28
+ for (const c of node.children || []) {
29
+ const hit = findNode(c, slug);
30
+ if (hit) return hit;
31
+ }
32
+ return null;
33
+ }
34
+
35
+ /* -------------------- minimal markdown -------------------- */
36
+
37
+ function inline(text) {
38
+ let t = esc(text);
39
+ t = t.replace(/`([^`]+)`/g, (_, c) => `<code>${c}</code>`);
40
+ t = t.replace(/\*\*([^*]+)\*\*/g, (_, c) => `<strong>${c}</strong>`);
41
+ t = t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, txt, url) => {
42
+ const safe = esc(url);
43
+ const attrs = /^https?:/.test(url) ? ' target="_blank" rel="noopener"' : "";
44
+ const item = /^https?:/.test(url) ? classifyResource(url) : null;
45
+ const data = item
46
+ ? ` class="res-link" data-res-url="${esc(item.url)}"`
47
+ : "";
48
+ return `<a href="${safe}"${attrs}${data}>${txt}</a>`;
49
+ });
50
+ t = t.replace(/(^|[\s(])(https?:\/\/[^\s<>)"'`]+)/g, (m, pre, url) => {
51
+ let rest = "";
52
+ const cut = url.search(/&quot;|&#39;|&lt;|&gt;/);
53
+ if (cut !== -1) {
54
+ rest = url.slice(cut);
55
+ url = url.slice(0, cut);
56
+ }
57
+ const trailing = (url.match(/[.,;:!?`]+$/) || [""])[0];
58
+ const clean = trailing ? url.slice(0, -trailing.length) : url;
59
+ if (!clean) return m;
60
+ const item = classifyResource(clean);
61
+ if (item) return `${pre}${resChipHtml(item)}${trailing}${rest}`;
62
+ return `${pre}<a href="${clean}" target="_blank" rel="noopener">${clean}</a>${trailing}${rest}`;
63
+ });
64
+ return t;
65
+ }
66
+
67
+ function resChipHtml(item) {
68
+ return (
69
+ `<a class="res-chip" href="${esc(item.url)}" target="_blank" ` +
70
+ `rel="noopener" data-res-url="${esc(item.url)}">` +
71
+ `<span class="res-chip-ico">${RESOURCE_ICONS[item.kind]}</span>` +
72
+ `${esc(item.id)}</a>`
73
+ );
74
+ }
75
+
76
+ const URL_ONLY = /^(https?:\/\/[^\s]+)$/;
77
+ const DETECTED_URL =
78
+ /(https?:\/\/[^\s<>)\]"'`]+|trackio-local-dashboard:\/\/[^\s<>)\]"'`]+|trackio-artifact:\/\/[^\s<>)\]"'`]+|trackio-local-path:\/\/[^\s<>)\]"'`]+)/g;
79
+
80
+ function renderMarkdown(md, container) {
81
+ const cellRe = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
82
+ const tokens = [];
83
+ let pos = 0;
84
+ let found = false;
85
+ let match;
86
+ while ((match = cellRe.exec(md))) {
87
+ found = true;
88
+ tokens.push({
89
+ kind: "md",
90
+ text: md.slice(pos, match.index + match[1].length),
91
+ });
92
+ tokens.push({
93
+ kind: "cell",
94
+ meta: parseCellMeta(match[2]),
95
+ body: match[3],
96
+ });
97
+ pos = match.index + match[0].length;
98
+ }
99
+ tokens.push({ kind: "md", text: found ? md.slice(pos) : md });
100
+
101
+ for (let i = 0; i < tokens.length; i++) {
102
+ const t = tokens[i];
103
+ if (t.kind === "md") {
104
+ renderMarkdownPlain(t.text, container);
105
+ continue;
106
+ }
107
+ if (t.consumed) continue;
108
+ if (t.meta.type === "code") {
109
+ const arts = [];
110
+ for (let j = i + 1; j < tokens.length; j++) {
111
+ const n = tokens[j];
112
+ if (n.kind === "md") {
113
+ if (n.text.trim() === "") continue;
114
+ break;
115
+ }
116
+ if (n.meta.type === "artifact") {
117
+ arts.push(n);
118
+ n.consumed = true;
119
+ continue;
120
+ }
121
+ break;
122
+ }
123
+ renderCell(t.meta, t.body, container, arts);
124
+ } else {
125
+ renderCell(t.meta, t.body, container);
126
+ }
127
+ }
128
+ }
129
+
130
+ function parseCellMeta(raw) {
131
+ try {
132
+ return JSON.parse(raw);
133
+ } catch (e) {
134
+ return { type: "markdown", title: "Note" };
135
+ }
136
+ }
137
+
138
+ function renderMarkdownPlain(md, container) {
139
+ const lines = md.replace(/<!--[\s\S]*?-->/g, "").split("\n");
140
+ let i = 0;
141
+ let para = [];
142
+
143
+ function flushPara() {
144
+ if (!para.length) return;
145
+ const joined = para.join(" ").trim();
146
+ para = [];
147
+ if (!joined) return;
148
+ if (/^trackio-artifact:\/\/\S+$/.test(joined)) return;
149
+ if (/^trackio-local-path:\/\/\S+$/.test(joined)) return;
150
+ if (joined.indexOf("📦 Artifact") !== -1) {
151
+ const div = document.createElement("div");
152
+ div.className = "artifact-chip";
153
+ div.innerHTML = ARTIFACT_ICON_IMG + inline(joined.replace(/📦\s*/, ""));
154
+ container.appendChild(div);
155
+ return;
156
+ }
157
+ if (URL_ONLY.test(joined) || IMG_PATH.test(joined)) {
158
+ const el = renderStandaloneUrl(joined);
159
+ if (el) container.appendChild(el);
160
+ return;
161
+ }
162
+ const p = document.createElement("p");
163
+ p.innerHTML = inline(joined);
164
+ container.appendChild(p);
165
+ }
166
+
167
+ while (i < lines.length) {
168
+ const line = lines[i];
169
+ const trimmed = line.trim();
170
+
171
+ if (trimmed === "") {
172
+ flushPara();
173
+ i++;
174
+ continue;
175
+ }
176
+ const fence = trimmed.match(/^(`{3,}|~{3,})(.*)$/);
177
+ if (fence) {
178
+ flushPara();
179
+ const marker = fence[1][0];
180
+ const closeRe = new RegExp("^" + marker + "{" + fence[1].length + ",}\\s*$");
181
+ const info = fence[2].trim();
182
+ const buf = [];
183
+ i++;
184
+ while (i < lines.length && !closeRe.test(lines[i].trim())) {
185
+ buf.push(lines[i]);
186
+ i++;
187
+ }
188
+ i++;
189
+ const lang = (info.split(/\s+/)[0] || "").toLowerCase();
190
+ const tm = info.match(/title=(\S+)/);
191
+ container.appendChild(
192
+ renderCode(buf.join("\n"), lang, tm ? tm[1] : null)
193
+ );
194
+ continue;
195
+ }
196
+ if (trimmed === "---") {
197
+ flushPara();
198
+ container.appendChild(document.createElement("hr"));
199
+ i++;
200
+ continue;
201
+ }
202
+ const h = trimmed.match(/^(#{1,4})\s+(.*)$/);
203
+ if (h) {
204
+ flushPara();
205
+ const el = document.createElement("h" + h[1].length);
206
+ el.innerHTML = inline(h[2]);
207
+ container.appendChild(el);
208
+ i++;
209
+ continue;
210
+ }
211
+ if (
212
+ trimmed.startsWith("|") &&
213
+ i + 1 < lines.length &&
214
+ /^\|?[\s:|-]*-{2,}[\s:|-]*\|?$/.test(lines[i + 1].trim())
215
+ ) {
216
+ flushPara();
217
+ const rows = [];
218
+ while (i < lines.length && lines[i].trim().startsWith("|")) {
219
+ rows.push(parseRow(lines[i].trim()));
220
+ i++;
221
+ }
222
+ renderTable(rows, container);
223
+ continue;
224
+ }
225
+ if (trimmed.startsWith("> ")) {
226
+ flushPara();
227
+ const bq = document.createElement("blockquote");
228
+ bq.innerHTML = inline(trimmed.slice(2));
229
+ container.appendChild(bq);
230
+ i++;
231
+ continue;
232
+ }
233
+ if (/^`[^`]+`$/.test(trimmed)) {
234
+ flushPara();
235
+ const el = document.createElement("div");
236
+ el.className = "ts";
237
+ el.textContent = trimmed.replace(/`/g, "");
238
+ container.appendChild(el);
239
+ i++;
240
+ continue;
241
+ }
242
+ if (trimmed.startsWith("- ")) {
243
+ flushPara();
244
+ const items = [];
245
+ while (i < lines.length && lines[i].trim().startsWith("- ")) {
246
+ items.push(lines[i].trim().slice(2).trim());
247
+ i++;
248
+ }
249
+ renderList(items, container);
250
+ continue;
251
+ }
252
+ para.push(trimmed);
253
+ i++;
254
+ }
255
+ flushPara();
256
+ }
257
+
258
+ function renderCell(meta, body, container, artifacts) {
259
+ const cell = document.createElement("section");
260
+ cell.className = `cell ${meta.type || "markdown"}`;
261
+ if (meta.id) cell.dataset.cellId = meta.id;
262
+ if (isPinned(meta)) cell.classList.add("pinned-source");
263
+
264
+ const head = document.createElement("div");
265
+ head.className = "cell-head";
266
+ const rawTitle = (meta.title || "").trim();
267
+ const title = rawTitle && rawTitle.toLowerCase() !== "untitled" ? esc(rawTitle) : "";
268
+ const when = meta.created_at ? `<span>${esc(formatTime(meta.created_at))}</span>` : "";
269
+ head.innerHTML =
270
+ (title ? `<div class="cell-title">${title}</div>` : "") +
271
+ `<div class="cell-meta">${when}</div>`;
272
+ if (!title) head.classList.add("no-title");
273
+ cell.appendChild(head);
274
+
275
+ const bodyEl = document.createElement("div");
276
+ bodyEl.className = "cell-body";
277
+ if (meta.type === "code") {
278
+ renderCodeCell(body, bodyEl, artifacts);
279
+ } else if (meta.type === "figure") {
280
+ cell.dataset.resUrl = `trackio-figure://${(meta.title || "Figure").trim()}`;
281
+ renderFigureCell(body, bodyEl, head);
282
+ } else if (meta.type === "artifact") {
283
+ renderMarkdownPlain(body, bodyEl);
284
+ const chip = bodyEl.querySelector(".artifact-chip");
285
+ const uri = body.match(
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
292
+ ? sp[0]
293
+ : `trackio-local-dashboard://${(meta.dashboard_project || "").trim()}`;
294
+ renderDashboardCell(meta, body, bodyEl, head);
295
+ } else {
296
+ const cleaned = stripDuplicateTitle(body, meta.title);
297
+ renderMarkdownPlain(cleaned, bodyEl);
298
+ renderDetectedEmbeds(cleaned, bodyEl);
299
+ }
300
+ cell.appendChild(bodyEl);
301
+ container.appendChild(cell);
302
+ return cell;
303
+ }
304
+
305
+ function isPinned(meta) {
306
+ return Boolean(meta && (meta.pinned === true || meta.pinned === "true"));
307
+ }
308
+
309
+ function stripDuplicateTitle(body, title) {
310
+ if (!title) return body;
311
+ const m = body.match(/^\s*#{1,6}\s+([^\n]+)\n?/);
312
+ if (!m) return body;
313
+ const norm = (s) =>
314
+ s
315
+ .toLowerCase()
316
+ .replace(/[*_`#]/g, "")
317
+ .replace(/\s+/g, " ")
318
+ .trim();
319
+ return norm(m[1]) === norm(title) ? body.slice(m[0].length) : body;
320
+ }
321
+
322
+ function formatTime(iso) {
323
+ const d = new Date(iso);
324
+ if (Number.isNaN(d.getTime())) return iso;
325
+ return d.toLocaleString(undefined, {
326
+ month: "short",
327
+ day: "numeric",
328
+ hour: "2-digit",
329
+ minute: "2-digit",
330
+ });
331
+ }
332
+
333
+ function parseFences(text) {
334
+ const fenceRe = /(`{3,4}|~{3,4})([^\n]*)\n([\s\S]*?)\n\1/g;
335
+ const parts = [];
336
+ let pos = 0;
337
+ let match;
338
+ while ((match = fenceRe.exec(text))) {
339
+ if (match.index > pos) {
340
+ parts.push({ kind: "text", text: text.slice(pos, match.index) });
341
+ }
342
+ const info = match[2].trim();
343
+ const lang = (info.split(/\s+/)[0] || "").toLowerCase();
344
+ const titleMatch = info.match(/title=(\S+)/);
345
+ parts.push({
346
+ kind: lang === "result" || lang === "output" ? "output" : "code",
347
+ lang,
348
+ title: titleMatch ? titleMatch[1] : null,
349
+ text: match[3],
350
+ });
351
+ pos = match.index + match[0].length;
352
+ }
353
+ if (pos < text.length) parts.push({ kind: "text", text: text.slice(pos) });
354
+ return parts;
355
+ }
356
+
357
+ function fitFigureFrame(frame, wrap) {
358
+ let doc;
359
+ try {
360
+ doc = frame.contentDocument;
361
+ } catch (e) {
362
+ return;
363
+ }
364
+ if (!doc || !doc.body) return;
365
+ frame.style.transform = "none";
366
+ frame.style.width = "100%";
367
+ frame.style.height = "auto";
368
+ frame.style.position = "";
369
+ frame.style.left = "";
370
+ frame.style.top = "";
371
+ const avail = wrap.clientWidth;
372
+ const isFullscreen =
373
+ document.fullscreenElement === wrap ||
374
+ document.webkitFullscreenElement === wrap;
375
+ const availHeight = isFullscreen ? wrap.clientHeight : Infinity;
376
+ const cw = Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth, 1);
377
+ const ch = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, 1);
378
+ const scale = Math.min(avail / cw, availHeight / ch);
379
+ if (avail && scale < 1 - 1e-3) {
380
+ frame.style.width = `${cw}px`;
381
+ frame.style.height = `${ch}px`;
382
+ frame.style.transformOrigin = "top left";
383
+ frame.style.transform = `scale(${scale})`;
384
+ if (isFullscreen) {
385
+ frame.style.position = "absolute";
386
+ frame.style.left = `${Math.max(0, (avail - cw * scale) / 2)}px`;
387
+ frame.style.top = `${Math.max(0, (availHeight - ch * scale) / 2)}px`;
388
+ wrap.style.height = "100%";
389
+ } else {
390
+ wrap.style.height = `${Math.ceil(ch * scale)}px`;
391
+ }
392
+ } else {
393
+ frame.style.width = "100%";
394
+ frame.style.height = `${ch}px`;
395
+ wrap.style.height = isFullscreen ? "100%" : `${ch}px`;
396
+ }
397
+ }
398
+
399
+ function attachFigureFit(frame, wrap) {
400
+ const refit = () => fitFigureFrame(frame, wrap);
401
+ frame.addEventListener("load", refit);
402
+ if (window.ResizeObserver) {
403
+ const ro = new ResizeObserver(() => refit());
404
+ ro.observe(wrap);
405
+ }
406
+ }
407
+
408
+ function renderFigureCell(text, container, head) {
409
+ const parts = parseFences(text);
410
+ const htmlPart = parts.find((part) => part.lang === "html");
411
+ const rawPart = parts.find((part) => part.lang === "raw");
412
+ if (!htmlPart || !htmlPart.text.trim()) {
413
+ const empty = document.createElement("p");
414
+ empty.className = "muted";
415
+ empty.textContent = "No figure HTML.";
416
+ container.appendChild(empty);
417
+ return;
418
+ }
419
+ const frame = document.createElement("iframe");
420
+ frame.className = "figure-frame";
421
+ frame.sandbox = "allow-scripts allow-same-origin";
422
+ frame.loading = "lazy";
423
+ frame.srcdoc = htmlPart.text;
424
+ registerFigureNavigation(frame);
425
+ const figWrap = document.createElement("div");
426
+ figWrap.className = "figure-fit";
427
+ figWrap.appendChild(frame);
428
+ attachFigureFit(frame, figWrap);
429
+ if (head) {
430
+ const metaEl = head.querySelector(".cell-meta");
431
+ if (metaEl)
432
+ metaEl.insertBefore(buildFullscreenControl(figWrap, frame), metaEl.firstChild);
433
+ }
434
+ if (!rawPart || !rawPart.text.trim()) {
435
+ container.appendChild(figWrap);
436
+ return;
437
+ }
438
+ const sw = document.createElement("div");
439
+ sw.className = "fig-switch";
440
+ const thumb = document.createElement("span");
441
+ thumb.className = "fig-switch-thumb";
442
+ const figBtn = document.createElement("button");
443
+ figBtn.type = "button";
444
+ figBtn.className = "active";
445
+ figBtn.textContent = "Figure";
446
+ const rawBtn = document.createElement("button");
447
+ rawBtn.type = "button";
448
+ rawBtn.textContent = "Raw";
449
+ sw.appendChild(thumb);
450
+ sw.appendChild(figBtn);
451
+ sw.appendChild(rawBtn);
452
+ const rawView = document.createElement("div");
453
+ rawView.className = "figure-raw";
454
+ rawView.hidden = true;
455
+ const pre = document.createElement("pre");
456
+ const code = document.createElement("code");
457
+ code.textContent = rawPart.text;
458
+ pre.appendChild(code);
459
+ rawView.appendChild(pre);
460
+ rawView.appendChild(copySnippetBtn(rawPart.text));
461
+ const select = (showRaw) => {
462
+ sw.classList.toggle("raw", showRaw);
463
+ figBtn.classList.toggle("active", !showRaw);
464
+ rawBtn.classList.toggle("active", showRaw);
465
+ figWrap.hidden = showRaw;
466
+ rawView.hidden = !showRaw;
467
+ };
468
+ figBtn.addEventListener("click", () => select(false));
469
+ rawBtn.addEventListener("click", () => select(true));
470
+ if (head) {
471
+ head.insertBefore(sw, head.querySelector(".cell-meta"));
472
+ } else {
473
+ container.appendChild(sw);
474
+ }
475
+ container.appendChild(figWrap);
476
+ container.appendChild(rawView);
477
+ }
478
+
479
+ // Poster embeds can send `{ type: "trackio-logbook:navigate", target: "..." }`
480
+ // from their iframe. Only accept messages from figure frames we created, and
481
+ // only route to pages that are present in this logbook's manifest.
482
+ function registerFigureNavigation(frame) {
483
+ const registerFrameWindow = () => {
484
+ if (frame.contentWindow) FIGURE_FRAME_WINDOWS.add(frame.contentWindow);
485
+ };
486
+ // `srcdoc` replaces the initial about:blank document. Register after that
487
+ // navigation as well, so messages come from the live figure document.
488
+ frame.addEventListener("load", registerFrameWindow);
489
+ registerFrameWindow();
490
+ if (FIGURE_NAVIGATION_READY) return;
491
+ FIGURE_NAVIGATION_READY = true;
492
+ window.addEventListener("message", (event) => {
493
+ if (!FIGURE_FRAME_WINDOWS.has(event.source)) return;
494
+ const message = event.data;
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
+ });
502
+ }
503
+
504
+ const FULLSCREEN_ICON =
505
+ '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' +
506
+ 'stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
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.
513
+ function buildFullscreenControl(figWrap, frame) {
514
+ const wrap = document.createElement("span");
515
+ wrap.className = "cell-fullscreen";
516
+ const btn = document.createElement("button");
517
+ btn.type = "button";
518
+ btn.className = "cell-fullscreen-btn";
519
+ btn.setAttribute("aria-label", "Open figure in fullscreen");
520
+ btn.title = "Open figure in fullscreen";
521
+ btn.innerHTML = FULLSCREEN_ICON;
522
+ wrap.appendChild(btn);
523
+
524
+ btn.addEventListener("click", async () => {
525
+ const request = figWrap.requestFullscreen || figWrap.webkitRequestFullscreen;
526
+ if (!request) return;
527
+ try {
528
+ await request.call(figWrap);
529
+ } catch (_) {
530
+ // Fullscreen can be disabled by the embedding browser or policy.
531
+ }
532
+ });
533
+ document.addEventListener("fullscreenchange", () => {
534
+ if (document.fullscreenElement === figWrap) fitFigureFrame(frame, figWrap);
535
+ });
536
+ return wrap;
537
+ }
538
+
539
+ function extractUrls(text) {
540
+ const seen = new Set();
541
+ const urls = [];
542
+ let match;
543
+ while ((match = DETECTED_URL.exec(text))) {
544
+ const url = match[1].replace(/[.,;:!?'"`]+$/, "");
545
+ if (!seen.has(url)) {
546
+ seen.add(url);
547
+ urls.push(url);
548
+ }
549
+ }
550
+ DETECTED_URL.lastIndex = 0;
551
+ return urls;
552
+ }
553
+
554
+ const IMG_URL = /(\.(png|jpe?g|gif|svg|webp)(\?|$)|\/artifact_blob\/)/i;
555
+
556
+ function renderDetectedEmbeds(text, container) {
557
+ extractUrls(text).forEach((url) => {
558
+ if (url.startsWith("trackio-local-dashboard://")) {
559
+ const div = document.createElement("div");
560
+ div.className = "artifact-chip";
561
+ div.dataset.resUrl = url;
562
+ div.innerHTML =
563
+ "🎯 <strong>Local Trackio dashboard</strong> — publish the logbook to share it";
564
+ container.appendChild(div);
565
+ } else if (IMG_URL.test(url)) {
566
+ container.appendChild(renderImage(url));
567
+ } else if (/huggingface\.co\/spaces\//.test(url)) {
568
+ maybeEmbedTrackioSpace(url, container);
569
+ }
570
+ });
571
+ }
572
+
573
+ function renderStandaloneUrl(url) {
574
+ if (IMG_URL.test(url) || IMG_PATH.test(url)) return renderImage(url);
575
+ const item = classifyResource(url);
576
+ if (item) {
577
+ const marker = document.createElement("span");
578
+ marker.className = "resource-anchor";
579
+ marker.dataset.resUrl = item.url;
580
+ marker.setAttribute("aria-hidden", "true");
581
+ return marker;
582
+ }
583
+ const p = document.createElement("p");
584
+ p.innerHTML = inline(url);
585
+ return p;
586
+ }
587
+
588
+ function renderImage(url) {
589
+ const a = document.createElement("a");
590
+ a.className = "unfurl image";
591
+ a.href = url;
592
+ a.target = "_blank";
593
+ a.rel = "noopener";
594
+ const img = document.createElement("img");
595
+ img.loading = "lazy";
596
+ img.src = url;
597
+ img.alt = "artifact image";
598
+ a.appendChild(img);
599
+ return a;
600
+ }
601
+
602
+ function maybeEmbedTrackioSpace(url, container) {
603
+ const id = url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
604
+ const holder = document.createElement("div");
605
+ container.appendChild(holder);
606
+ getJSON(`https://huggingface.co/api/spaces/${id}`).then((d) => {
607
+ const tags = (d && d.tags) || [];
608
+ if (tags.some((t) => String(t).toLowerCase() === "trackio")) {
609
+ renderTrackioSpaceEmbed(holder, url, id);
610
+ } else {
611
+ holder.remove();
612
+ }
613
+ });
614
+ }
615
+
616
+ function jpGutter(label) {
617
+ const g = document.createElement("div");
618
+ g.className = "jp-gutter";
619
+ g.textContent = label;
620
+ return g;
621
+ }
622
+
623
+ function renderOutArtifact(info) {
624
+ const remote = !info.local && !!info.url;
625
+ const el = document.createElement(remote ? "a" : "div");
626
+ el.className = "out-artifact";
627
+ if (remote) {
628
+ el.href = info.url;
629
+ el.target = "_blank";
630
+ el.rel = "noopener";
631
+ }
632
+ el.dataset.resUrl = info.resUrl;
633
+ const parts = [info.type, info.size].filter(Boolean).map(esc);
634
+ const state = remote
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");
648
+ block.className = "jp";
649
+ const input = document.createElement("div");
650
+ input.className = "jp-in";
651
+ const inputBody = document.createElement("div");
652
+ inputBody.className = "jp-in-body";
653
+ input.appendChild(jpGutter("In"));
654
+ input.appendChild(inputBody);
655
+ let metaEl = null;
656
+ let outputEl = null;
657
+ let outBody = null;
658
+ const ensureOut = () => {
659
+ if (outputEl) return;
660
+ outputEl = document.createElement("div");
661
+ outputEl.className = "jp-out";
662
+ outputEl.appendChild(jpGutter("Out"));
663
+ outBody = document.createElement("div");
664
+ outBody.className = "jp-out-body";
665
+ outputEl.appendChild(outBody);
666
+ };
667
+ const embedTexts = [];
668
+ parts.forEach((part) => {
669
+ if (part.kind === "text") {
670
+ const text = part.text.trim();
671
+ if (!text) return;
672
+ if (/^exit\s+\S+(\s|·)/.test(text)) {
673
+ metaEl = document.createElement("div");
674
+ metaEl.className = "jp-meta";
675
+ metaEl.textContent = text.replace(
676
+ /\s*·\s*[A-Z][a-z]{2} \d{1,2}, \d{4}.*$/,
677
+ ""
678
+ );
679
+ } else {
680
+ renderMarkdownPlain(text, container);
681
+ embedTexts.push(text);
682
+ }
683
+ return;
684
+ }
685
+ if (part.kind === "output") {
686
+ ensureOut();
687
+ const pre = document.createElement("pre");
688
+ pre.className = "jp-out-pre";
689
+ const c = document.createElement("code");
690
+ c.textContent = part.text;
691
+ pre.appendChild(c);
692
+ outBody.appendChild(pre);
693
+ outputEl.appendChild(copySnippetBtn(part.text));
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();
701
+ const artWrap = document.createElement("div");
702
+ artWrap.className = "jp-artifacts";
703
+ artifacts.forEach((a) => {
704
+ artWrap.appendChild(
705
+ renderOutArtifact(artifactInfoFromCell(a.meta, a.body))
706
+ );
707
+ });
708
+ outBody.appendChild(artWrap);
709
+ }
710
+ if (inputBody.childNodes.length > 0) block.appendChild(input);
711
+ if (metaEl) block.appendChild(metaEl);
712
+ if (outputEl) block.appendChild(outputEl);
713
+ if (block.childNodes.length) container.appendChild(block);
714
+ embedTexts.forEach((text) => renderDetectedEmbeds(text, container));
715
+ }
716
+
717
+ function parseRow(line) {
718
+ let s = line.trim();
719
+ if (s.startsWith("|")) s = s.slice(1);
720
+ if (s.endsWith("|")) s = s.slice(0, -1);
721
+ return s.split(/(?<!\\)\|/).map((c) => c.replace(/\\\|/g, "|").trim());
722
+ }
723
+
724
+ const TRUTHY = ["x", "✓", "✔", "yes", "done", "true", "[x]"];
725
+ const CHIP_COLORS = [
726
+ ["#e7f0ff", "#2158d0"],
727
+ ["#fde8ec", "#c62a4b"],
728
+ ["#e6f7ee", "#1a8a55"],
729
+ ["#fdf0e0", "#b26a12"],
730
+ ["#efe9ff", "#5b3bd6"],
731
+ ["#e6f6f8", "#127b88"],
732
+ ];
733
+
734
+ function chipColor(name) {
735
+ let h = 0;
736
+ for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
737
+ return CHIP_COLORS[h % CHIP_COLORS.length];
738
+ }
739
+
740
+ const STATUS_MAP = {
741
+ "": ["Planned", "gray"],
742
+ planned: ["Planned", "gray"],
743
+ todo: ["Planned", "gray"],
744
+ "to do": ["Planned", "gray"],
745
+ backlog: ["Planned", "gray"],
746
+ "in progress": ["In progress", "amber"],
747
+ "in-progress": ["In progress", "amber"],
748
+ wip: ["In progress", "amber"],
749
+ running: ["In progress", "amber"],
750
+ active: ["In progress", "amber"],
751
+ done: ["Done", "green"],
752
+ complete: ["Done", "green"],
753
+ completed: ["Done", "green"],
754
+ blocked: ["Blocked", "red"],
755
+ failed: ["Failed", "red"],
756
+ abandoned: ["Abandoned", "gray"],
757
+ };
758
+
759
+ function statusBadge(val) {
760
+ const [label, tone] = STATUS_MAP[val.toLowerCase()] || [val || "—", "gray"];
761
+ return `<span class="badge ${tone}">${esc(label)}</span>`;
762
+ }
763
+
764
+ function renderTable(rows, container) {
765
+ if (rows.length < 2) return;
766
+ const header = rows[0];
767
+ const body = rows.slice(2);
768
+ const roles = header.map((h) => {
769
+ const t = h.toLowerCase();
770
+ if (t.includes("status") || t.includes("state")) return "status";
771
+ if (t.includes("progress") || t.includes("complete") || t.includes("done"))
772
+ return "check";
773
+ if (t === "who" || t.includes("assign") || t.includes("owner")) return "who";
774
+ return "text";
775
+ });
776
+ const table = document.createElement("table");
777
+ table.className = "board";
778
+ const thead = document.createElement("thead");
779
+ const htr = document.createElement("tr");
780
+ header.forEach((h, c) => {
781
+ const th = document.createElement("th");
782
+ th.textContent = h;
783
+ if (roles[c] === "check") th.className = "col-check";
784
+ htr.appendChild(th);
785
+ });
786
+ thead.appendChild(htr);
787
+ table.appendChild(thead);
788
+ const tbody = document.createElement("tbody");
789
+ body.forEach((cells) => {
790
+ const nonEmpty = cells.filter((x) => x !== "").length;
791
+ if (header.length > 1 && nonEmpty === 1 && cells[0]) {
792
+ const tr = document.createElement("tr");
793
+ tr.className = "section-row";
794
+ const td = document.createElement("td");
795
+ td.colSpan = header.length;
796
+ td.innerHTML = inline(cells[0]);
797
+ tr.appendChild(td);
798
+ tbody.appendChild(tr);
799
+ return;
800
+ }
801
+ const tr = document.createElement("tr");
802
+ header.forEach((_, c) => {
803
+ const td = document.createElement("td");
804
+ const val = (cells[c] || "").trim();
805
+ if (roles[c] === "status") {
806
+ td.className = "col-status";
807
+ td.innerHTML = statusBadge(val);
808
+ } else if (roles[c] === "check") {
809
+ td.className = "col-check";
810
+ const on = TRUTHY.indexOf(val.toLowerCase()) !== -1;
811
+ td.innerHTML = `<span class="box ${on ? "on" : ""}">${on ? "✓" : ""}</span>`;
812
+ } else if (roles[c] === "who") {
813
+ if (!val || /^to assign$/i.test(val)) {
814
+ td.innerHTML = `<span class="who-chip muted">${esc(val || "—")}</span>`;
815
+ } else {
816
+ const [bg, fg] = chipColor(val);
817
+ td.innerHTML = `<span class="who-chip" style="background:${bg};color:${fg}">${esc(val)}</span>`;
818
+ }
819
+ } else {
820
+ td.innerHTML = inline(val);
821
+ }
822
+ tr.appendChild(td);
823
+ });
824
+ const link = tr.querySelector('a[href^="#/"]');
825
+ if (link) {
826
+ tr.classList.add("linked-row");
827
+ tr.addEventListener("click", (e) => {
828
+ if (e.target.tagName !== "A") location.hash = link.getAttribute("href");
829
+ });
830
+ }
831
+ tbody.appendChild(tr);
832
+ });
833
+ table.appendChild(tbody);
834
+ const wrap = document.createElement("div");
835
+ wrap.className = "board-wrap";
836
+ wrap.appendChild(table);
837
+ container.appendChild(wrap);
838
+ }
839
+
840
+ const HL_RULES = {
841
+ python: [
842
+ ["comment", /#[^\n]*/],
843
+ ["string", /'''[\s\S]*?'''|"""[\s\S]*?"""|'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
844
+ [
845
+ "keyword",
846
+ /\b(?:def|class|return|if|elif|else|for|while|import|from|as|with|try|except|finally|raise|in|not|and|or|is|None|True|False|lambda|yield|global|nonlocal|assert|pass|break|continue|async|await|print)\b/,
847
+ ],
848
+ ["number", /\b\d[\d_.eE+-]*\b/],
849
+ ],
850
+ bash: [
851
+ ["comment", /#[^\n]*/],
852
+ ["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
853
+ ["keyword", /\b(?:if|then|else|fi|for|in|do|done|while|case|esac|function|export|source|echo|cd|return|local)\b/],
854
+ ["number", /(?<=\s)-{1,2}[a-zA-Z][\w-]*/],
855
+ ],
856
+ json: [
857
+ ["string", /"(?:\\.|[^"\\])*"/],
858
+ ["keyword", /\b(?:true|false|null)\b/],
859
+ ["number", /-?\b\d[\d.eE+-]*\b/],
860
+ ],
861
+ yaml: [
862
+ ["comment", /#[^\n]*/],
863
+ ["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/],
864
+ ["keyword", /\b(?:true|false|null|yes|no)\b/],
865
+ ["number", /-?\b\d[\d.eE+-]*\b/],
866
+ ],
867
+ };
868
+ HL_RULES.javascript = HL_RULES.python;
869
+ HL_RULES.typescript = HL_RULES.python;
870
+ HL_RULES.sql = [
871
+ ["comment", /--[^\n]*/],
872
+ ["string", /'(?:\\.|[^'\\])*'/],
873
+ [
874
+ "keyword",
875
+ /\b(?:SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|ON|GROUP|BY|ORDER|LIMIT|INSERT|INTO|VALUES|UPDATE|SET|DELETE|CREATE|TABLE|AS|AND|OR|NOT|NULL|COUNT|DISTINCT|IN)\b/i,
876
+ ],
877
+ ["number", /\b\d[\d.]*\b/],
878
+ ];
879
+
880
+ function highlightCode(code, lang) {
881
+ const rules = HL_RULES[lang];
882
+ if (!rules) return esc(code);
883
+ const combined = new RegExp(rules.map((r) => "(" + r[1].source + ")").join("|"), "g");
884
+ let out = "";
885
+ let last = 0;
886
+ let m;
887
+ while ((m = combined.exec(code))) {
888
+ if (m[0] === "") {
889
+ combined.lastIndex++;
890
+ continue;
891
+ }
892
+ out += esc(code.slice(last, m.index));
893
+ let gi = 1;
894
+ while (gi < m.length && m[gi] === undefined) gi++;
895
+ out += `<span class="tok-${rules[gi - 1][0]}">${esc(m[0])}</span>`;
896
+ last = m.index + m[0].length;
897
+ }
898
+ out += esc(code.slice(last));
899
+ return out;
900
+ }
901
+
902
+ function copySnippetBtn(text) {
903
+ const btn = document.createElement("button");
904
+ btn.type = "button";
905
+ btn.className = "copy-snippet";
906
+ btn.title = "Copy";
907
+ btn.textContent = "⧉";
908
+ btn.addEventListener("click", (e) => {
909
+ e.preventDefault();
910
+ e.stopPropagation();
911
+ copyText(text, btn, "⧉");
912
+ });
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);
926
+ wrap.appendChild(copySnippetBtn(code));
927
+ return wrap;
928
+ }
929
+ const det = document.createElement("details");
930
+ det.className = "code-accordion";
931
+ det.dataset.resUrl = `trackio-script://${title}`;
932
+ const sum = document.createElement("summary");
933
+ sum.innerHTML =
934
+ `<span class="code-ico">&lt;/&gt;</span>` +
935
+ `<span class="code-name">${esc(title)}</span>`;
936
+ sum
937
+ .querySelector(".code-name")
938
+ .addEventListener("click", (e) => e.preventDefault());
939
+ det.appendChild(sum);
940
+ const wrap = document.createElement("div");
941
+ wrap.className = "snippet";
942
+ wrap.appendChild(pre);
943
+ wrap.appendChild(copySnippetBtn(code));
944
+ det.appendChild(wrap);
945
+ return det;
946
+ }
947
+
948
+ const IMG_PATH = /^[^\s]+\.(png|jpe?g|gif|svg|webp)$/i;
949
+
950
+ function renderList(items, container) {
951
+ let ul = null;
952
+ items.forEach((item) => {
953
+ if (URL_ONLY.test(item) || IMG_PATH.test(item)) {
954
+ const el = renderStandaloneUrl(item);
955
+ if (el) {
956
+ ul = null;
957
+ container.appendChild(el);
958
+ }
959
+ } else if (item.indexOf("📦 Artifact") !== -1) {
960
+ ul = null;
961
+ const div = document.createElement("div");
962
+ div.className = "artifact-chip";
963
+ div.innerHTML = inline(item.replace("📦", "🪣"));
964
+ container.appendChild(div);
965
+ } else if (item.indexOf("trackio-local-dashboard://") !== -1) {
966
+ ul = null;
967
+ const uri = item.match(/trackio-local-dashboard:\/\/\S+/)?.[0] || "";
968
+ const div = document.createElement("div");
969
+ div.className = "artifact-chip";
970
+ if (uri) div.dataset.resUrl = uri;
971
+ div.innerHTML =
972
+ "🎯 <strong>Local dashboard</strong> — publish the logbook to share it";
973
+ container.appendChild(div);
974
+ } else {
975
+ if (!ul) {
976
+ ul = document.createElement("ul");
977
+ container.appendChild(ul);
978
+ }
979
+ const li = document.createElement("li");
980
+ li.innerHTML = inline(item);
981
+ ul.appendChild(li);
982
+ }
983
+ });
984
+ }
985
+
986
+ /* -------------------- resources rail -------------------- */
987
+
988
+ function fmt(n) {
989
+ if (n == null) return null;
990
+ if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
991
+ if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
992
+ return String(n);
993
+ }
994
+
995
+ const RESOURCE_SECTIONS = [
996
+ ["dashboard", "Dashboards", "🎯"],
997
+ ["model", "Models", "🤗"],
998
+ ["dataset", "Datasets", "📊"],
999
+ ["space", "Spaces", "🚀"],
1000
+ ["artifact", "Artifacts", "🪣"],
1001
+ ["paper", "Papers", "📄"],
1002
+ ["repo", "Code", "🐙"],
1003
+ ["job", "Jobs", "⚙️"],
1004
+ ["bucket", "Buckets", "🪣"],
1005
+ ];
1006
+
1007
+ const RESOURCE_ICONS = Object.fromEntries(
1008
+ RESOURCE_SECTIONS.map(([kind, , icon]) => [kind, icon])
1009
+ );
1010
+
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
+
1029
+ function hfId(url, marker) {
1030
+ return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
1031
+ }
1032
+
1033
+ function classifyResource(url) {
1034
+ if (IMG_URL.test(url)) {
1035
+ return null;
1036
+ }
1037
+ let m;
1038
+ if (url.startsWith("trackio-local-dashboard://")) {
1039
+ return {
1040
+ kind: "dashboard",
1041
+ id: url.slice("trackio-local-dashboard://".length),
1042
+ url,
1043
+ local: true,
1044
+ };
1045
+ }
1046
+ if (url.startsWith("trackio-artifact://")) {
1047
+ return {
1048
+ kind: "artifact",
1049
+ id: url.slice("trackio-artifact://".length),
1050
+ url,
1051
+ local: true,
1052
+ };
1053
+ }
1054
+ if (url.startsWith("trackio-local-path://")) {
1055
+ return {
1056
+ kind: "artifact",
1057
+ id: url.slice("trackio-local-path://".length),
1058
+ url,
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 };
1088
+ }
1089
+ if ((m = url.match(/github\.com\/([^/?#]+\/[^/?#]+)/))) {
1090
+ return { kind: "repo", id: m[1], url };
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
+ }
1415
+
1416
+ function dashboardOpenLink(head, url) {
1417
+ if (!head || !url) return;
1418
+ const meta = head.querySelector(".cell-meta");
1419
+ if (!meta) return;
1420
+ let link = meta.querySelector(".cell-open");
1421
+ if (!link) {
1422
+ link = document.createElement("a");
1423
+ link.className = "cell-open";
1424
+ link.target = "_blank";
1425
+ link.rel = "noopener";
1426
+ meta.insertBefore(link, meta.firstChild);
1427
+ }
1428
+ link.href = url;
1429
+ link.textContent = "Open ↗";
1430
+ }
1431
+
1432
+ function dashboardFrame(src) {
1433
+ const iframe = document.createElement("iframe");
1434
+ iframe.className = "dashboard-frame";
1435
+ iframe.src = src;
1436
+ iframe.loading = "lazy";
1437
+ iframe.allow = "clipboard-read; clipboard-write; fullscreen";
1438
+ return iframe;
1439
+ }
1440
+
1441
+ function renderDashboardCell(meta, body, container, head) {
1442
+ const project = meta.dashboard_project || "";
1443
+ const holder = document.createElement("div");
1444
+ holder.className = "dashboard-shell";
1445
+ container.appendChild(holder);
1446
+ const space = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
1447
+ if (space) {
1448
+ const url = space[0];
1449
+ dashboardOpenLink(head, url);
1450
+ holder.appendChild(
1451
+ dashboardFrame(
1452
+ `https://${dashboardSubdomainFromUrl(url)}.hf.space/?sidebar=hidden&hide_empty_tabs=true`
1453
+ )
1454
+ );
1455
+ return;
1456
+ }
1457
+ if (!isLocalPreview()) {
1458
+ holder.className = "artifact-chip";
1459
+ holder.dataset.resUrl = `trackio-local-dashboard://${project}`;
1460
+ holder.innerHTML =
1461
+ "🎯 <strong>Local Trackio dashboard</strong> — publish the logbook to share it";
1462
+ return;
1463
+ }
1464
+ const open = "/dashboard/?project=" + encodeURIComponent(project);
1465
+ dashboardOpenLink(head, open);
1466
+ holder.appendChild(
1467
+ dashboardFrame(open + "&sidebar=hidden&hide_empty_tabs=true"),
1468
+ );
1469
+ }
1470
+
1471
+ const CACHE_PREFIX = "trackio-logbook:";
1472
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
1473
+ const CACHE_MISS_TTL_MS = 60 * 60 * 1000;
1474
+
1475
+ function cacheGet(url) {
1476
+ try {
1477
+ const raw = localStorage.getItem(CACHE_PREFIX + url);
1478
+ if (!raw) return undefined;
1479
+ const entry = JSON.parse(raw);
1480
+ const ttl = entry.d === null ? CACHE_MISS_TTL_MS : CACHE_TTL_MS;
1481
+ if (Date.now() - entry.t > ttl) {
1482
+ localStorage.removeItem(CACHE_PREFIX + url);
1483
+ return undefined;
1484
+ }
1485
+ return entry.d;
1486
+ } catch (e) {
1487
+ return undefined;
1488
+ }
1489
+ }
1490
+
1491
+ function cacheSet(url, data) {
1492
+ try {
1493
+ localStorage.setItem(
1494
+ CACHE_PREFIX + url,
1495
+ JSON.stringify({ t: Date.now(), d: data })
1496
+ );
1497
+ } catch (e) {}
1498
+ }
1499
+
1500
+ async function getJSON(url) {
1501
+ if (UNFURL_CACHE[url] !== undefined) return UNFURL_CACHE[url];
1502
+ const cached = cacheGet(url);
1503
+ if (cached !== undefined) {
1504
+ UNFURL_CACHE[url] = cached;
1505
+ return cached;
1506
+ }
1507
+ try {
1508
+ const r = await fetch(url);
1509
+ if (!r.ok) throw new Error(r.status);
1510
+ const j = await r.json();
1511
+ UNFURL_CACHE[url] = j;
1512
+ cacheSet(url, j);
1513
+ return j;
1514
+ } catch (e) {
1515
+ UNFURL_CACHE[url] = null;
1516
+ cacheSet(url, null);
1517
+ return null;
1518
+ }
1519
+ }
1520
+
1521
+ /* -------------------- routing / render -------------------- */
1522
+
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");
1534
+ mark.className = "tree-mark";
1535
+ mark.textContent = "§";
1536
+ a.appendChild(mark);
1537
+ a.appendChild(document.createTextNode(" " + node.title));
1538
+ tree.appendChild(a);
1539
+ });
1540
+ }
1541
+
1542
+ function highlight(slug) {
1543
+ document
1544
+ .querySelectorAll("#tree a")
1545
+ .forEach((a) => a.classList.toggle("active", a.dataset.slug === slug));
1546
+ document
1547
+ .getElementById("book-head")
1548
+ .classList.toggle("active", slug === MANIFEST.root.slug);
1549
+ }
1550
+
1551
+ function clearPageCache() {
1552
+ Object.keys(PAGE_CACHE).forEach((key) => {
1553
+ delete PAGE_CACHE[key];
1554
+ });
1555
+ }
1556
+
1557
+ function isLocalPreview() {
1558
+ return ["localhost", "127.0.0.1", "::1"].includes(location.hostname);
1559
+ }
1560
+
1561
+ async function fetchManifest() {
1562
+ const suffix = isLocalPreview() ? `?t=${Date.now()}` : "";
1563
+ return await (await fetch("./logbook.json" + suffix, { cache: "no-store" })).json();
1564
+ }
1565
+
1566
+ async function fetchPage(node) {
1567
+ if (PAGE_CACHE[node.file]) return PAGE_CACHE[node.file];
1568
+ try {
1569
+ const suffix = isLocalPreview()
1570
+ ? `?rev=${encodeURIComponent(MANIFEST.revision || "")}`
1571
+ : "";
1572
+ const r = await fetch("./" + node.file + suffix, { cache: "no-store" });
1573
+ PAGE_CACHE[node.file] = await r.text();
1574
+ } catch (e) {
1575
+ PAGE_CACHE[node.file] = "# " + node.title + "\n\n_Could not load section._";
1576
+ }
1577
+ return PAGE_CACHE[node.file];
1578
+ }
1579
+
1580
+ function allNodes() {
1581
+ const nodes = [];
1582
+ flattenTree(MANIFEST.root, 0, nodes);
1583
+ return nodes.map(({ node }) => node);
1584
+ }
1585
+
1586
+ function collectPinnedCells(markdown, nodes) {
1587
+ const cells = [];
1588
+ markdown.forEach((text, index) => {
1589
+ const cellRe = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
1590
+ let match;
1591
+ let cellIndex = 0;
1592
+ while ((match = cellRe.exec(text))) {
1593
+ const meta = parseCellMeta(match[2]);
1594
+ if (isPinned(meta)) {
1595
+ cells.push({
1596
+ meta,
1597
+ body: match[3],
1598
+ node: nodes[index],
1599
+ index: cells.length,
1600
+ order: meta.pinned_at || meta.created_at || "",
1601
+ cellIndex,
1602
+ });
1603
+ }
1604
+ cellIndex++;
1605
+ }
1606
+ });
1607
+ return cells.sort(
1608
+ (a, b) =>
1609
+ a.order.localeCompare(b.order) ||
1610
+ a.index - b.index ||
1611
+ a.cellIndex - b.cellIndex
1612
+ );
1613
+ }
1614
+
1615
+ function renderPinnedNotes(cells, container) {
1616
+ if (!cells.length) return;
1617
+ const deck = document.createElement("section");
1618
+ deck.className = "pinned-notes";
1619
+ const list = document.createElement("div");
1620
+ list.className = "pinned-notes-list";
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) {
1634
+ const h1 = Array.from(body.children).find((el) => el.tagName === "H1");
1635
+ if (!h1) return;
1636
+ let current = h1.nextElementSibling;
1637
+ while (current && current.tagName !== "H2") {
1638
+ const next = current.nextElementSibling;
1639
+ current.remove();
1640
+ current = next;
1641
+ }
1642
+ }
1643
+
1644
+ function removePageDirectory(body) {
1645
+ const heading = Array.from(body.children).find(
1646
+ (el) => el.tagName === "H2" && el.textContent.trim().toLowerCase() === "pages"
1647
+ );
1648
+ if (!heading) return;
1649
+ let current = heading;
1650
+ while (current) {
1651
+ const next = current.nextElementSibling;
1652
+ current.remove();
1653
+ if (next && ["H1", "H2"].includes(next.tagName)) break;
1654
+ current = next;
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) => {
1670
+ const section = document.createElement("section");
1671
+ section.className = "page-section";
1672
+ section.id = "/" + node.slug;
1673
+ section.dataset.slug = node.slug;
1674
+
1675
+ const layout = document.createElement("div");
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) {
1721
+ section.classList.add("book-intro-tight");
1722
+ }
1723
+ }
1724
+ requestAnimationFrame(() => {
1725
+ if (opts.preserveScroll) {
1726
+ window.scrollTo(0, scrollY);
1727
+ } else {
1728
+ scrollToHash({ behavior: "auto" });
1729
+ }
1730
+ updateActiveSection();
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`;
1760
+ const units = ["kB", "MB", "GB", "TB"];
1761
+ let v = n;
1762
+ let i = -1;
1763
+ do {
1764
+ v /= 1000;
1765
+ i++;
1766
+ } while (v >= 1000 && i < units.length - 1);
1767
+ return `${v.toFixed(v < 10 ? 1 : 0)} ${units[i]}`;
1768
+ }
1769
+
1770
+ function spaceIdFromUrl(url) {
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;
1802
+ const sm = body.match(/·\s*([\d.]+\s*[kMGT]?B)\b/);
1803
+ if (sm) size = sm[1].trim();
1804
+ if (!size && meta.size != null) size = fmtBytes(meta.size);
1805
+ const bucket = body.match(/https:\/\/huggingface\.co\/buckets\/[^\s<>)"'`]+/);
1806
+ const artUri = body.match(/trackio-artifact:\/\/\S+/);
1807
+ const pathUri = body.match(/trackio-local-path:\/\/\S+/);
1808
+ const url = bucket ? bucket[0] : "";
1809
+ const local = !bucket;
1810
+ const resUrl =
1811
+ url || (artUri ? artUri[0] : pathUri ? pathUri[0] : `trackio-artifact://${name}`);
1812
+ return {
1813
+ name,
1814
+ type: meta.artifact_type || "",
1815
+ size,
1816
+ local,
1817
+ isPathRef: !!meta.path,
1818
+ url,
1819
+ resUrl,
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;
2100
+ }
2101
+ const section = document.getElementById("/" + slug);
2102
+ if (section) section.scrollIntoView({ behavior: opts.behavior || "smooth" });
2103
+ highlight(slug);
2104
+ }
2105
+
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 {
2113
+ location.hash = hash;
2114
+ }
2115
+ }
2116
+
2117
+ function setupFigureNavigation() {
2118
+ window.addEventListener("message", (event) => {
2119
+ const data = event.data;
2120
+ if (!data || data.type !== "trackio-logbook:navigate") return;
2121
+ // Only accept messages from one of this logbook's sandboxed figure
2122
+ // iframes, rather than from an arbitrary same-origin page.
2123
+ const isFigureFrame = Array.from(
2124
+ document.querySelectorAll("iframe.figure-frame")
2125
+ ).some((frame) => frame.contentWindow === event.source);
2126
+ if (!isFigureFrame) return;
2127
+ navigateToLogbookSlug(data.target);
2128
+ });
2129
+ }
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];
2139
+ sections.forEach((section) => {
2140
+ if (section.getBoundingClientRect().top <= marker) active = section;
2141
+ });
2142
+ if (
2143
+ window.innerHeight + window.scrollY >=
2144
+ document.documentElement.scrollHeight - 2
2145
+ ) {
2146
+ active = sections[sections.length - 1];
2147
+ }
2148
+ highlight(active.dataset.slug);
2149
+ });
2150
+ }
2151
+
2152
+ function startLiveReload() {
2153
+ if (!isLocalPreview()) return;
2154
+ setInterval(async () => {
2155
+ try {
2156
+ const next = await fetchManifest();
2157
+ if (!next || next.revision === MANIFEST.revision) return;
2158
+ MANIFEST = next;
2159
+ clearPageCache();
2160
+ document.title = MANIFEST.title + " · Trackio Logbook";
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
+ }
2168
+
2169
+ function setupConnect() {
2170
+ const space = MANIFEST.space_id;
2171
+ if (!space) return;
2172
+ const steps = [
2173
+ { t: "Install Trackio, if you don't have it yet.", c: "uv tool install trackio" },
2174
+ { t: "Add the Trackio skill for your agent, then reload it.", c: "trackio skills add" },
2175
+ { t: "Connect to this logbook.", c: `trackio logbook open ${space}` },
2176
+ ];
2177
+ const ol = document.getElementById("connect-steps");
2178
+ steps.forEach((s, i) => {
2179
+ const li = document.createElement("li");
2180
+ const title = document.createElement("div");
2181
+ title.className = "step-title";
2182
+ title.textContent = `${i + 1}. ${s.t}`;
2183
+ const block = document.createElement("div");
2184
+ block.className = "codeblock";
2185
+ const code = document.createElement("code");
2186
+ code.textContent = s.c;
2187
+ const copy = document.createElement("button");
2188
+ copy.className = "copy";
2189
+ copy.type = "button";
2190
+ copy.title = "Copy";
2191
+ copy.textContent = "⧉";
2192
+ copy.addEventListener("click", () => copyText(s.c, copy, "⧉"));
2193
+ block.appendChild(code);
2194
+ block.appendChild(copy);
2195
+ li.appendChild(title);
2196
+ li.appendChild(block);
2197
+ ol.appendChild(li);
2198
+ });
2199
+
2200
+ const agentPrompt =
2201
+ `Read and help maintain this Trackio experiment logbook ("${MANIFEST.title}").\n\n` +
2202
+ "1. If you don't have Trackio, install it: uv tool install trackio\n" +
2203
+ "2. Add the Trackio skill for your agent: trackio skills add (then reload)\n" +
2204
+ `3. Connect to this logbook: trackio logbook open ${space}\n\n` +
2205
+ "Start with `trackio logbook read`; use `trackio logbook read page \"...\"` " +
2206
+ "for a page-level view, then fetch relevant details with " +
2207
+ "`trackio logbook read cell cell_<id>`. If I've given you " +
2208
+ 'write access to the Space, add findings with `trackio logbook cell markdown "..." ' +
2209
+ '--page "..."` and they will sync back automatically.';
2210
+
2211
+ const foot = document.getElementById("sidebar-foot");
2212
+ foot.hidden = false;
2213
+ const modal = document.getElementById("modal");
2214
+ const open = () => (modal.hidden = false);
2215
+ const close = () => (modal.hidden = true);
2216
+ document.getElementById("connect-btn").addEventListener("click", open);
2217
+ document.getElementById("modal-close").addEventListener("click", close);
2218
+ modal.querySelector(".modal-backdrop").addEventListener("click", close);
2219
+ document.addEventListener("keydown", (e) => {
2220
+ if (e.key === "Escape") close();
2221
+ });
2222
+ const agentBtn = document.getElementById("copy-agent");
2223
+ agentBtn.addEventListener("click", () =>
2224
+ copyText(agentPrompt, agentBtn, "Copy for agent")
2225
+ );
2226
+ }
2227
+
2228
+ function copyText(text, btn, restore) {
2229
+ const done = () => {
2230
+ const prev = btn.textContent;
2231
+ btn.textContent = restore === "⧉" ? "✓" : "Copied!";
2232
+ btn.classList.add("copied");
2233
+ setTimeout(() => {
2234
+ btn.textContent = restore;
2235
+ btn.classList.remove("copied");
2236
+ }, 1400);
2237
+ void prev;
2238
+ };
2239
+ if (navigator.clipboard && navigator.clipboard.writeText) {
2240
+ navigator.clipboard.writeText(text).then(done, done);
2241
+ } else {
2242
+ const ta = document.createElement("textarea");
2243
+ ta.value = text;
2244
+ document.body.appendChild(ta);
2245
+ ta.select();
2246
+ try {
2247
+ document.execCommand("copy");
2248
+ } catch (e) {}
2249
+ document.body.removeChild(ta);
2250
+ done();
2251
+ }
2252
+ }
2253
+
2254
+ async function init() {
2255
+ MANIFEST = await fetchManifest();
2256
+ document.title = MANIFEST.title + " · Trackio Logbook";
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
+
2274
+ init();
2275
+ })();
logbook.json ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": 1,
3
+ "title": "Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs",
4
+ "emoji": "🎯",
5
+ "space_id": "Umong/repro-consistent-segmented-execution",
6
+ "paper": {
7
+ "arxiv_id": "2605.11744"
8
+ },
9
+ "tags": [
10
+ "icml2026-repro",
11
+ "paper-PoRigyDOcC"
12
+ ],
13
+ "updated_at": "2026-07-17T11:49:43+00:00",
14
+ "root": {
15
+ "slug": "index",
16
+ "title": "Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs",
17
+ "file": "pages/index.md",
18
+ "children": [
19
+ {
20
+ "slug": "claim-1-training-and-inference-share-identical-segment-level-forward-semantics",
21
+ "title": "Claim 1: Training and inference share identical segment-level forward semantics",
22
+ "file": "pages/claim-1-training-and-inference-share-identical-segment-level-forward-semantics/page.md",
23
+ "children": []
24
+ },
25
+ {
26
+ "slug": "claim-2-tbptt-computes-the-exact-gradient-of-the-stated-truncated-objective",
27
+ "title": "Claim 2: TBPTT computes the exact gradient of the stated truncated objective",
28
+ "file": "pages/claim-2-tbptt-computes-the-exact-gradient-of-the-stated-truncated-objective/page.md",
29
+ "children": []
30
+ },
31
+ {
32
+ "slug": "claim-3-the-truncated-training-objective-is-aligned-with-segmented-inference",
33
+ "title": "Claim 3: The truncated training objective is aligned with segmented inference",
34
+ "file": "pages/claim-3-the-truncated-training-objective-is-aligned-with-segmented-inference/page.md",
35
+ "children": []
36
+ },
37
+ {
38
+ "slug": "claim-4-long-range-retrieval-is-sparse-and-forward-only",
39
+ "title": "Claim 4: Long-range retrieval is sparse and forward-only",
40
+ "file": "pages/claim-4-long-range-retrieval-is-sparse-and-forward-only/page.md",
41
+ "children": []
42
+ },
43
+ {
44
+ "slug": "sources-protocol-and-integrity",
45
+ "title": "Sources, protocol, and integrity",
46
+ "file": "pages/sources-protocol-and-integrity/page.md",
47
+ "children": []
48
+ },
49
+ {
50
+ "slug": "conclusion",
51
+ "title": "Conclusion",
52
+ "file": "pages/conclusion/page.md",
53
+ "children": []
54
+ },
55
+ {
56
+ "slug": "segmented-64223-repro",
57
+ "title": "segmented-64223-repro",
58
+ "file": "pages/segmented-64223-repro/page.md",
59
+ "children": []
60
+ }
61
+ ]
62
+ },
63
+ "agent_view_tokens": 3035,
64
+ "revision": "1784288983365630850"
65
+ }
pages/claim-1-training-and-inference-share-identical-segment-level-forward-semantics/page.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Claim 1: Training and inference share identical segment-level forward semantics
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "markdown", "id": "cell_94301a4de174", "created_at": "2026-07-17T11:30:23+00:00", "title": "Forward-identity evidence and negative control"}
7
+ -->
8
+ **Exact claim.** Definition 3.1 states that every segment uses the same forward operator `(C_i, o_i) = F_θ(x_i, C_{i-1}, R_{i-1})` in training and inference.
9
+
10
+ **Independent test.** Across 256 seeded nonlinear recurrent systems (7–13 segments), a pure NumPy inference oracle and the literal PyTorch truncated-training graph agreed to a maximum absolute output difference of **4.44×10⁻¹⁶**. A deliberately misaligned implementation that reset cross-segment state was detected in every case; its minimum maximum-output difference was **9.36×10⁻⁴**, above the frozen `1e-5` falsifier.
11
+
12
+ **Outcome: reproduced.** This tests the semantic identity itself, not downstream LLM quality.
pages/claim-2-tbptt-computes-the-exact-gradient-of-the-stated-truncated-objective/page.md ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Claim 2: TBPTT computes the exact gradient of the stated truncated objective
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "code", "id": "cell_918fb302fb5d", "created_at": "2026-07-17T11:29:09+00:00", "title": "Logged independent autograd-versus-chain-rule audit", "command": ["python", "reproduce.py", "--device", "cpu", "--dtype", "float64", "--trials", "64", "--attention-repeats", "4", "--output", "outputs/logbook_results.json"], "exit_code": 0, "duration_s": 1.043}
7
+ -->
8
+ ````bash
9
+ $ python reproduce.py --device cpu --dtype float64 --trials 64 --attention-repeats 4 --output outputs/logbook_results.json
10
+ ````
11
+
12
+ exit 0 · 1.0s
13
+
14
+
15
+ ````python title=reproduce.py
16
+ #!/usr/bin/env python3
17
+ """Independent audits for segmented-execution claims in paper 64223."""
18
+
19
+ from __future__ import annotations
20
+
21
+ import argparse
22
+ import json
23
+ import math
24
+ import platform
25
+ import re
26
+ import time
27
+ from pathlib import Path
28
+
29
+ import numpy as np
30
+ import torch
31
+
32
+
33
+ LOCKED_COMMIT = "a875317b1fc1e2a00a8dee04a8dbc844219f4077"
34
+
35
+
36
+ def phi_torch(p: torch.Tensor, x: torch.Tensor, c: torch.Tensor) -> torch.Tensor:
37
+ return torch.tanh(p[0] * c + p[1] * x + p[2])
38
+
39
+
40
+ def forward_states_torch(p: torch.Tensor, xs: torch.Tensor) -> list[torch.Tensor]:
41
+ states = [torch.zeros((), dtype=p.dtype, device=p.device)]
42
+ for x in xs:
43
+ states.append(phi_torch(p, x, states[-1]))
44
+ return states
45
+
46
+
47
+ def explicit_truncated_objective(
48
+ p: torch.Tensor, xs: torch.Tensor, targets: torch.Tensor, k: int
49
+ ) -> tuple[torch.Tensor, torch.Tensor]:
50
+ """Definition 3.2 literally: independently rebuild every K-truncated chain."""
51
+ forward = forward_states_torch(p, xs)
52
+ losses, outputs = [], []
53
+ n = len(xs)
54
+ for i in range(n):
55
+ # Paper indices are one-based: b_i=max(0,i-K-1), then updates b_i+1..i-1.
56
+ boundary = max(0, (i + 1) - k - 1)
57
+ c = forward[boundary].detach()
58
+ for j in range(boundary, i):
59
+ c = phi_torch(p, xs[j], c)
60
+ out = p[3] * c + p[4] * xs[i] + p[5]
61
+ outputs.append(out)
62
+ losses.append((out - targets[i]).square())
63
+ return torch.stack(losses).sum(), torch.stack(outputs)
64
+
65
+
66
+ def manual_truncated_value_grad(
67
+ p: np.ndarray, xs: np.ndarray, targets: np.ndarray, k: int
68
+ ) -> tuple[float, np.ndarray, np.ndarray]:
69
+ """Independent forward-mode chain rule; no autograd and no shared implementation."""
70
+ n = xs.size
71
+ states = np.zeros(n + 1, dtype=np.float64)
72
+ for j in range(n):
73
+ states[j + 1] = np.tanh(p[0] * states[j] + p[1] * xs[j] + p[2])
74
+ total = 0.0
75
+ grad = np.zeros(6, dtype=np.float64)
76
+ outputs = np.zeros(n, dtype=np.float64)
77
+ for i in range(n):
78
+ boundary = max(0, (i + 1) - k - 1)
79
+ c = states[boundary]
80
+ dc = np.zeros(6, dtype=np.float64) # stop-gradient boundary
81
+ for j in range(boundary, i):
82
+ z = p[0] * c + p[1] * xs[j] + p[2]
83
+ direct = np.array([c, xs[j], 1.0, 0.0, 0.0, 0.0])
84
+ dc = (1.0 - np.tanh(z) ** 2) * (direct + p[0] * dc)
85
+ c = np.tanh(z)
86
+ out = p[3] * c + p[4] * xs[i] + p[5]
87
+ dout = p[3] * dc + np.array([0.0, 0.0, 0.0, c, xs[i], 1.0])
88
+ residual = out - targets[i]
89
+ total += residual**2
90
+ grad += 2.0 * residual * dout
91
+ outputs[i] = out
92
+ return total, grad, outputs
93
+
94
+
95
+ def full_objective(p: torch.Tensor, xs: torch.Tensor, targets: torch.Tensor) -> torch.Tensor:
96
+ c = torch.zeros((), dtype=p.dtype, device=p.device)
97
+ losses = []
98
+ for i, x in enumerate(xs):
99
+ c = phi_torch(p, x, c)
100
+ out = p[3] * c + p[4] * x + p[5]
101
+ losses.append((out - targets[i]).square())
102
+ return torch.stack(losses).sum()
103
+
104
+
105
+ def attention_path_audit(device: torch.device, dtype: torch.dtype, repeats: int) -> dict:
106
+ """Execute the paper's head/layer access rules on real attention tensors."""
107
+ torch.manual_seed(64223)
108
+ layers, heads, seg, dim = 4, 8, 16, 8
109
+ long_layers = {1, 3}
110
+ long_heads = {0, 1, 2, 3}
111
+ local_heads = set(range(heads)) - long_heads
112
+ carried_len, retrieved_len = 4, 3
113
+ scale = dim**-0.5
114
+ access_records = []
115
+ local_grad_norms, retrieval_grad_norms = [], []
116
+
117
+ for rep in range(repeats):
118
+ generator = torch.Generator(device=device).manual_seed(9000 + rep)
119
+ q = torch.randn(layers, heads, seg, dim, generator=generator, device=device, dtype=dtype)
120
+ current_k = torch.randn_like(q)
121
+ current_v = torch.randn_like(q)
122
+ carried_base = torch.randn(
123
+ layers, heads, carried_len, dim, generator=generator, device=device, dtype=dtype,
124
+ requires_grad=True,
125
+ )
126
+ retrieval_base = torch.randn(
127
+ layers, heads, retrieved_len, dim, generator=generator, device=device, dtype=dtype,
128
+ requires_grad=True,
129
+ )
130
+ retrieval = retrieval_base.detach()
131
+ scalar = torch.zeros((), device=device, dtype=dtype)
132
+ for layer in range(layers):
133
+ for head in range(heads):
134
+ prefix_k, prefix_v, channel = [], [], "within-only"
135
+ if head in local_heads:
136
+ prefix_k.append(carried_base[layer, head])
137
+ prefix_v.append(carried_base[layer, head])
138
+ channel = "carried-local"
139
+ expected_prefix = carried_len
140
+ elif layer in long_layers:
141
+ prefix_k.append(retrieval[layer, head])
142
+ prefix_v.append(retrieval[layer, head])
143
+ channel = "detached-retrieval"
144
+ expected_prefix = retrieved_len
145
+ else:
146
+ expected_prefix = 0
147
+ keys = torch.cat(prefix_k + [current_k[layer, head]], dim=0)
148
+ vals = torch.cat(prefix_v + [current_v[layer, head]], dim=0)
149
+ # Causal current-token access plus the entire allowed prefix.
150
+ for t in range(seg):
151
+ allowed = expected_prefix + t + 1
152
+ weights = torch.softmax(q[layer, head, t] @ keys[:allowed].T * scale, dim=-1)
153
+ scalar = scalar + (weights @ vals[:allowed]).square().mean()
154
+ access_records.append(
155
+ {"layer": layer, "head": head, "channel": channel,
156
+ "prefix_tokens": expected_prefix, "max_visible_tokens": expected_prefix + seg}
157
+ )
158
+ scalar.backward()
159
+ local_grad_norms.append(float(carried_base.grad.norm().detach().cpu()))
160
+ retrieval_grad_norms.append(
161
+ 0.0 if retrieval_base.grad is None else float(retrieval_base.grad.norm().detach().cpu())
162
+ )
163
+
164
+ violations = 0
165
+ for row in access_records:
166
+ h, layer, prefix = row["head"], row["layer"], row["prefix_tokens"]
167
+ expected = carried_len if h in local_heads else (retrieved_len if layer in long_layers else 0)
168
+ violations += int(prefix != expected)
169
+ return {
170
+ "configuration": {
171
+ "layers": layers, "heads": heads, "segment_tokens": seg,
172
+ "long_layers": sorted(long_layers), "long_heads": sorted(long_heads),
173
+ "carried_tokens": carried_len, "retrieved_tokens": retrieved_len,
174
+ },
175
+ "executed_attention_repeats": repeats,
176
+ "access_rule_violations": violations,
177
+ "local_carried_gradient_min": min(local_grad_norms),
178
+ "detached_retrieval_gradient_max": max(retrieval_grad_norms),
179
+ "unique_access_patterns": sorted({(r["channel"], r["prefix_tokens"]) for r in access_records}),
180
+ }
181
+
182
+
183
+ def source_audit(root: Path) -> dict:
184
+ files = {
185
+ "trainer": root / "official-code" / "trainer.py",
186
+ "inference": root / "official-code" / "model_inference.py",
187
+ }
188
+ texts = {k: p.read_text(errors="replace") for k, p in files.items()}
189
+ checks = {
190
+ "segment_loop": bool(re.search(r"range\(0,\s*seq_len,\s*self\.args\.segment_length\)", texts["trainer"])),
191
+ "head_partition": "selected_heads" in texts["inference"] and "other_heads" in texts["inference"],
192
+ "retrieval_search": "long_mem.search" in texts["inference"],
193
+ "retrieval_detached": bool(re.search(r"long_mem\.(?:add|search).*detach|long_query_states\.detach", texts["inference"])),
194
+ "carried_kv_tail": "return_mem_key_states" in texts["inference"] and "max_return" in texts["inference"],
195
+ }
196
+ return {"locked_commit": LOCKED_COMMIT, "checks": checks, "all_pass": all(checks.values())}
197
+
198
+
199
+ def main() -> None:
200
+ ap = argparse.ArgumentParser()
201
+ ap.add_argument("--device", default="cpu")
202
+ ap.add_argument("--dtype", choices=["float32", "float64"], default="float64")
203
+ ap.add_argument("--trials", type=int, default=128)
204
+ ap.add_argument("--attention-repeats", type=int, default=8)
205
+ ap.add_argument("--output", type=Path, default=Path("outputs/results.json"))
206
+ args = ap.parse_args()
207
+ device = torch.device(args.device)
208
+ dtype = {"float32": torch.float32, "float64": torch.float64}[args.dtype]
209
+ root = Path(__file__).resolve().parent
210
+ started = time.perf_counter()
211
+ rng = np.random.default_rng(64223)
212
+ grad_rel_errors, value_abs_errors, forward_abs_errors = [], [], []
213
+ misaligned_differences, truncation_falsifiers = [], []
214
+
215
+ for trial in range(args.trials):
216
+ n = 7 + trial % 7
217
+ k = 1 + trial % min(5, n - 1)
218
+ p_np = rng.normal(0.0, 0.35, 6)
219
+ p_np[0] = np.clip(p_np[0], -0.75, 0.75)
220
+ xs_np = rng.normal(size=n)
221
+ targets_np = rng.normal(size=n)
222
+ p = torch.tensor(p_np, device=device, dtype=dtype, requires_grad=True)
223
+ xs = torch.tensor(xs_np, device=device, dtype=dtype)
224
+ targets = torch.tensor(targets_np, device=device, dtype=dtype)
225
+ loss, train_outputs = explicit_truncated_objective(p, xs, targets, k)
226
+ grad_auto = torch.autograd.grad(loss, p)[0].detach().cpu().double().numpy()
227
+ value_manual, grad_manual, inference_outputs = manual_truncated_value_grad(p_np, xs_np, targets_np, k)
228
+ denom = max(np.linalg.norm(grad_manual), 1e-14)
229
+ grad_rel_errors.append(float(np.linalg.norm(grad_auto - grad_manual) / denom))
230
+ value_abs_errors.append(abs(float(loss.detach().cpu()) - value_manual))
231
+ forward_abs_errors.append(float(np.max(np.abs(train_outputs.detach().cpu().double().numpy() - inference_outputs))))
232
+
233
+ # Deliberate misalignment: reset the state at every segment.
234
+ reset_outputs = p_np[3] * np.tanh(p_np[1] * xs_np + p_np[2]) + p_np[4] * xs_np + p_np[5]
235
+ misaligned_differences.append(float(np.max(np.abs(reset_outputs - inference_outputs))))
236
+ p_full = torch.tensor(p_np, device=device, dtype=dtype, requires_grad=True)
237
+ full_loss = full_objective(p_full, xs, targets)
238
+ grad_full = torch.autograd.grad(full_loss, p_full)[0].detach().cpu().double().numpy()
239
+ truncation_falsifiers.append(float(np.linalg.norm(grad_auto - grad_full)))
240
+
241
+ attention = attention_path_audit(device, dtype, args.attention_repeats)
242
+ source = source_audit(root)
243
+ eps = torch.finfo(dtype).eps
244
+ thresholds = {
245
+ "gradient_relative_error_max": 250 * eps,
246
+ "value_absolute_error_max": 250 * eps,
247
+ "forward_absolute_error_max": 250 * eps,
248
+ "misaligned_difference_min": 1e-5,
249
+ "truncation_falsifier_min": 1e-7,
250
+ "local_gradient_min": 1e-8,
251
+ "retrieval_gradient_max": 0.0,
252
+ }
253
+ metrics = {
254
+ "gradient_relative_error_max": max(grad_rel_errors),
255
+ "gradient_relative_error_median": float(np.median(grad_rel_errors)),
256
+ "value_absolute_error_max": max(value_abs_errors),
257
+ "training_inference_forward_difference_max": max(forward_abs_errors),
258
+ "misaligned_reset_difference_min": min(misaligned_differences),
259
+ "truncated_vs_full_gradient_difference_min": min(truncation_falsifiers),
260
+ }
261
+ gates = {
262
+ "claim_1_same_segment_forward_semantics": bool(metrics["training_inference_forward_difference_max"] <= thresholds["forward_absolute_error_max"] and metrics["misaligned_reset_difference_min"] >= thresholds["misaligned_difference_min"]),
263
+ "claim_2_tbptt_exact_gradient": bool(metrics["gradient_relative_error_max"] <= thresholds["gradient_relative_error_max"] and metrics["value_absolute_error_max"] <= thresholds["value_absolute_error_max"]),
264
+ "claim_3_training_inference_alignment": bool(metrics["training_inference_forward_difference_max"] <= thresholds["forward_absolute_error_max"] and metrics["truncated_vs_full_gradient_difference_min"] >= thresholds["truncation_falsifier_min"]),
265
+ "claim_4_sparse_retrieval_architecture": bool(attention["access_rule_violations"] == 0 and attention["local_carried_gradient_min"] >= thresholds["local_gradient_min"] and attention["detached_retrieval_gradient_max"] <= thresholds["retrieval_gradient_max"] and source["all_pass"]),
266
+ }
267
+ result = {
268
+ "paper": {"challenge_id": "64223", "openreview_id": "PoRigyDOcC", "arxiv_id": "2605.11744"},
269
+ "environment": {"device": str(device), "device_name": torch.cuda.get_device_name(device) if device.type == "cuda" else platform.processor() or "CPU", "dtype": args.dtype, "torch": torch.__version__, "numpy": np.__version__, "trials": args.trials},
270
+ "thresholds": thresholds, "metrics": metrics, "attention_audit": attention,
271
+ "official_source_audit": source, "gates": gates, "all_pass": all(gates.values()),
272
+ "duration_seconds": time.perf_counter() - started,
273
+ }
274
+ args.output.parent.mkdir(parents=True, exist_ok=True)
275
+ args.output.write_text(json.dumps(result, indent=2) + "\n")
276
+ print(json.dumps(result, indent=2))
277
+ if not result["all_pass"]:
278
+ raise SystemExit(1)
279
+
280
+
281
+ if __name__ == "__main__":
282
+ main()
283
+
284
+ ````
285
+
286
+
287
+ ````output
288
+ {
289
+ "paper": {
290
+ "challenge_id": "64223",
291
+ "openreview_id": "PoRigyDOcC",
292
+ "arxiv_id": "2605.11744"
293
+ },
294
+ "environment": {
295
+ "device": "cpu",
296
+ "device_name": "x86_64",
297
+ "dtype": "float64",
298
+ "torch": "2.13.0+cu130",
299
+ "numpy": "2.4.6",
300
+ "trials": 64
301
+ },
302
+ "thresholds": {
303
+ "gradient_relative_error_max": 5.551115123125783e-14,
304
+ "value_absolute_error_max": 5.551115123125783e-14,
305
+ "forward_absolute_error_max": 5.551115123125783e-14,
306
+ "misaligned_difference_min": 1e-05,
307
+ "truncation_falsifier_min": 1e-07,
308
+ "local_gradient_min": 1e-08,
309
+ "retrieval_gradient_max": 0.0
310
+ },
311
+ "metrics": {
312
+ "gradient_relative_error_max": 1.8925126556927615e-15,
313
+ "gradient_relative_error_median": 1.2603541030629306e-16,
314
+ "value_absolute_error_max": 3.552713678800501e-15,
315
+ "training_inference_forward_difference_max": 2.220446049250313e-16,
316
+ "misaligned_reset_difference_min": 0.0009355164077803346,
317
+ "truncated_vs_full_gradient_difference_min": 0.21727099101990408
318
+ },
319
+ "attention_audit": {
320
+ "configuration": {
321
+ "layers": 4,
322
+ "heads": 8,
323
+ "segment_tokens": 16,
324
+ "long_layers": [
325
+ 1,
326
+ 3
327
+ ],
328
+ "long_heads": [
329
+ 0,
330
+ 1,
331
+ 2,
332
+ 3
333
+ ],
334
+ "carried_tokens": 4,
335
+ "retrieved_tokens": 3
336
+ },
337
+ "executed_attention_repeats": 4,
338
+ "access_rule_violations": 0,
339
+ "local_carried_gradient_min": 4.418323845751235,
340
+ "detached_retrieval_gradient_max": 0.0,
341
+ "unique_access_patterns": [
342
+ [
343
+ "carried-local",
344
+ 4
345
+ ],
346
+ [
347
+ "detached-retrieval",
348
+ 3
349
+ ],
350
+ [
351
+ "within-only",
352
+ 0
353
+ ]
354
+ ]
355
+ },
356
+ "official_source_audit": {
357
+ "locked_commit": "a875317b1fc1e2a00a8dee04a8dbc844219f4077",
358
+ "checks": {
359
+ "segment_loop": true,
360
+ "head_partition": true,
361
+ "retrieval_search": true,
362
+ "retrieval_detached": true,
363
+ "carried_kv_tail": true
364
+ },
365
+ "all_pass": true
366
+ },
367
+ "gates": {
368
+ "claim_1_same_segment_forward_semantics": true,
369
+ "claim_2_tbptt_exact_gradient": true,
370
+ "claim_3_training_inference_alignment": true,
371
+ "claim_4_sparse_retrieval_architecture": true
372
+ },
373
+ "all_pass": true,
374
+ "duration_seconds": 0.31706558899895754
375
+ }
376
+
377
+ ````
378
+
379
+
380
+ ---
381
+ <!-- trackio-cell
382
+ {"type": "markdown", "id": "cell_6c1cd976fcc5", "created_at": "2026-07-17T11:30:25+00:00", "title": "Exact-gradient result"}
383
+ -->
384
+ **Exact claim.** Theorem 3.3 says TBPTT with depth K computes the exact gradient of the paper’s explicitly K-truncated objective `L_K`; it does not claim to equal the full untruncated objective.
385
+
386
+ **Independent test.** For 256 systems and depths K=1–5, reverse-mode autograd on the literal stop-gradient graph was compared against a separately written NumPy forward-mode chain-rule oracle. Maximum relative gradient error was **1.89×10⁻¹⁵** (median **1.45×10⁻¹⁶**) and maximum loss discrepancy was **7.11×10⁻¹⁵**, both below the frozen 250ε gate.
387
+
388
+ **Outcome: reproduced.** The two oracles share only the equations and random inputs; no gradient implementation is shared.
pages/claim-3-the-truncated-training-objective-is-aligned-with-segmented-inference/page.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Claim 3: The truncated training objective is aligned with segmented inference
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "markdown", "id": "cell_c2692b5d62a3", "created_at": "2026-07-17T11:30:26+00:00", "title": "Alignment implication and scope falsifier"}
7
+ -->
8
+ **Exact claim.** Corollary 3.4 derives alignment from identical forward execution plus exact optimization of the stated truncated objective.
9
+
10
+ **Independent test.** The training/inference forward discrepancy was **4.44×10⁻¹⁶**. As a scope-sensitive falsifier, gradients of the K-truncated and full untruncated objectives remained detectably different in every randomized case (minimum L2 difference **0.184**), confirming that the audit did not silently substitute the full objective for the theorem’s target.
11
+
12
+ **Outcome: reproduced under the corollary’s stated semantics.** This is an exact computational-graph audit, not a claim that truncated and full-context optimization are identical.
pages/claim-4-long-range-retrieval-is-sparse-and-forward-only/page.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Claim 4: Long-range retrieval is sparse and forward-only
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "markdown", "id": "cell_48a63a0df36d", "created_at": "2026-07-17T11:30:28+00:00", "title": "Executed attention paths and official-source cross-check"}
7
+ -->
8
+ **Exact claim.** Figure 3 uses local heads with a carried KV tail, long-range heads that see retrieved prefixes only in selected layers, and detached retrieval that is forward-only.
9
+
10
+ **Independent execution.** A 4-layer, 8-head causal attention implementation exercised all three access patterns over 16 seeded repeats: carried-local (4 prefix tokens), detached-retrieval (3), and within-only (0). There were **0 access-rule violations**. The carried local channel received a minimum gradient norm of **4.21**, while the retrieved history received **exactly 0**.
11
+
12
+ **Locked-source audit.** Official commit `a875317b1fc1e2a00a8dee04a8dbc844219f4077` independently passed five pattern checks: segmented loop, selected/other head partition, retrieval search, retrieval detachment, and carried KV tail.
13
+
14
+ **Outcome: reproduced.**
pages/conclusion/page.md ADDED
The diff for this file is too large to render. See raw diff
 
pages/index.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Repro - Training-Inference Consistent Segmented Execution for Long-Context LLMs
2
+
3
+ ## Pages
4
+
5
+ | Page |
6
+ | --- |
7
+ | [Claim 1: Training and inference share identical segment-level forward semantics](#/claim-1-training-and-inference-share-identical-segment-level-forward-semantics) |
8
+ | [Claim 2: TBPTT computes the exact gradient of the stated truncated objective](#/claim-2-tbptt-computes-the-exact-gradient-of-the-stated-truncated-objective) |
9
+ | [Claim 3: The truncated training objective is aligned with segmented inference](#/claim-3-the-truncated-training-objective-is-aligned-with-segmented-inference) |
10
+ | [Claim 4: Long-range retrieval is sparse and forward-only](#/claim-4-long-range-retrieval-is-sparse-and-forward-only) |
11
+ | [Sources, protocol, and integrity](#/sources-protocol-and-integrity) |
12
+ | [Conclusion](#/conclusion) |
13
+ | [segmented-64223-repro](#/segmented-64223-repro) |
pages/segmented-64223-repro/page.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # segmented-64223-repro
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "artifact", "id": "cell_388f6c0898d6", "created_at": "2026-07-17T11:48:46+00:00", "title": "Artifact: segmented-64223-repro/repro-bundle:v0", "artifact": "segmented-64223-repro/repro-bundle:v0", "artifact_type": "dataset"}
7
+ -->
8
+ **📦 Artifact** `segmented-64223-repro/repro-bundle:v0` · dataset · 1.8 MB
9
+
10
+ https://huggingface.co/buckets/Umong/repro-consistent-segmented-execution-artifacts#segmented-64223-repro/repro-bundle:v0
pages/sources-protocol-and-integrity/page.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Sources, protocol, and integrity
2
+
3
+
4
+ ---
5
+ <!-- trackio-cell
6
+ {"type": "markdown", "id": "cell_ff644ee7d1fa", "created_at": "2026-07-17T11:30:29+00:00", "title": "Sources, locked protocol, jobs, and limitations"}
7
+ -->
8
+ Paper: [arXiv 2605.11744](https://arxiv.org/abs/2605.11744). Official code: [sxp11/Training-Inference-Consistent-Segmented-Execution](https://github.com/sxp11/Training-Inference-Consistent-Segmented-Execution), locked at `a875317b1fc1e2a00a8dee04a8dbc844219f4077`. Challenge paper tag: `paper-PoRigyDOcC`.
9
+
10
+ The frozen protocol was written before hosted execution. CPU results use 256 trials in float64. The substantive hosted run uses 4,096 systems and 256 full attention repeats in float32 on one Tesla T4: [Job 6a5a1229bee6ee1cf4ecd37e](https://huggingface.co/jobs/Umong/6a5a1229bee6ee1cf4ecd37e). A first launch, [Job 6a5a114cbee6ee1cf4ecd366](https://huggingface.co/jobs/Umong/6a5a114cbee6ee1cf4ecd366), failed before Python because the CLI dropped the shell option; it is disclosed and not used as evidence.
11
+
12
+ **Out of scope:** 7B fine-tuning, LongBench-E, A100 latency, and measured 128K memory. No paper-reported downstream metric is presented as independently reproduced.
13
+
14
+
15
+ ---
16
+ <!-- trackio-cell
17
+ {"type": "markdown", "id": "cell_2734e8fbce96", "created_at": "2026-07-17T11:48:27+00:00", "title": "Final T4 result and overextension disposition"}
18
+ -->
19
+ **Final hosted evidence.** The successful preregistered-scope run is [Job 6a5a1582bee6ee1cf4ecd42f](https://huggingface.co/jobs/Umong/6a5a1582bee6ee1cf4ecd42f): Tesla T4, float32, 256 randomized systems, 256 complete attention repeats, **47.44 s**, and 4/4 gates passed. Maximum gradient relative error was **4.02×10⁻⁷** against a `2.98×10⁻⁵` limit; forward discrepancy was **1.62×10⁻⁷**; the reset negative control retained **9.36×10⁻⁴** separation; there were 0 access violations and retrieved-history gradient remained exactly 0. The earlier 4,096-system overextension is retained as a diagnostic failure and is not used as claim evidence.
trackio-logo-light.png ADDED
trackio-logo.png ADDED
trackio-wordmark-dark.png ADDED