@soederpop/luca 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assistants/codingAssistant/ABOUT.md +3 -1
- package/assistants/codingAssistant/CORE.md +2 -4
- package/assistants/codingAssistant/hooks.ts +9 -10
- package/assistants/codingAssistant/tools.ts +9 -0
- package/assistants/inkbot/ABOUT.md +13 -2
- package/assistants/inkbot/CORE.md +278 -39
- package/assistants/inkbot/hooks.ts +0 -8
- package/assistants/inkbot/tools.ts +24 -18
- package/assistants/researcher/ABOUT.md +5 -0
- package/assistants/researcher/CORE.md +46 -0
- package/assistants/researcher/hooks.ts +16 -0
- package/assistants/researcher/tools.ts +237 -0
- package/commands/inkbot.ts +526 -194
- package/docs/examples/assistant-hooks-reference.ts +171 -0
- package/package.json +1 -1
- package/public/slides-ai-native.html +902 -0
- package/public/slides-intro.html +974 -0
- package/src/agi/features/assistant.ts +432 -62
- package/src/agi/features/conversation.ts +170 -10
- package/src/bootstrap/generated.ts +1 -1
- package/src/cli/build-info.ts +2 -2
- package/src/helper.ts +12 -3
- package/src/introspection/generated.agi.ts +1105 -873
- package/src/introspection/generated.node.ts +757 -757
- package/src/introspection/generated.web.ts +1 -1
- package/src/python/generated.ts +1 -1
- package/src/scaffolds/generated.ts +1 -1
- package/test/assistant-hooks.test.ts +306 -0
- package/test/assistant.test.ts +1 -1
- package/test/fork-and-research.test.ts +450 -0
- package/SPEC.md +0 -304
|
@@ -0,0 +1,902 @@
|
|
|
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.0">
|
|
6
|
+
<title>Luca: AI-Native Architecture</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
|
10
|
+
<style>
|
|
11
|
+
/* ===========================================
|
|
12
|
+
THEME: Same system as intro deck
|
|
13
|
+
Slightly more neon/electric vibe for AI topic
|
|
14
|
+
=========================================== */
|
|
15
|
+
:root {
|
|
16
|
+
--bg-primary: #07070d;
|
|
17
|
+
--bg-secondary: #0e0e18;
|
|
18
|
+
--bg-card: #151520;
|
|
19
|
+
--text-primary: #f0ede6;
|
|
20
|
+
--text-secondary: #7a7a8a;
|
|
21
|
+
--text-muted: #4a4a5a;
|
|
22
|
+
--accent: #e8a634;
|
|
23
|
+
--accent-glow: rgba(232, 166, 52, 0.25);
|
|
24
|
+
--accent-dim: rgba(232, 166, 52, 0.08);
|
|
25
|
+
--blue: #5b8def;
|
|
26
|
+
--blue-glow: rgba(91, 141, 239, 0.2);
|
|
27
|
+
--cyan: #22d3ee;
|
|
28
|
+
--cyan-glow: rgba(34, 211, 238, 0.15);
|
|
29
|
+
--green: #4ade80;
|
|
30
|
+
--orange: #f59e0b;
|
|
31
|
+
--purple: #c4b5fd;
|
|
32
|
+
--code-bg: #0a0a12;
|
|
33
|
+
--border: rgba(255, 255, 255, 0.06);
|
|
34
|
+
|
|
35
|
+
--font-display: 'Inter', sans-serif;
|
|
36
|
+
--font-mono: 'JetBrains Mono', monospace;
|
|
37
|
+
|
|
38
|
+
--title-size: clamp(2rem, 5.5vw, 4.5rem);
|
|
39
|
+
--h2-size: clamp(1.5rem, 4vw, 3rem);
|
|
40
|
+
--h3-size: clamp(1rem, 2vw, 1.5rem);
|
|
41
|
+
--body-size: clamp(0.8rem, 1.3vw, 1.1rem);
|
|
42
|
+
--small-size: clamp(0.65rem, 1vw, 0.85rem);
|
|
43
|
+
--code-size: clamp(0.65rem, 1.1vw, 0.9rem);
|
|
44
|
+
|
|
45
|
+
--slide-padding: clamp(1.5rem, 5vw, 5rem);
|
|
46
|
+
--content-gap: clamp(0.75rem, 2vw, 2rem);
|
|
47
|
+
|
|
48
|
+
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
|
52
|
+
html, body { height: 100%; overflow-x: hidden; }
|
|
53
|
+
html { scroll-snap-type: y mandatory; scroll-behavior: smooth; }
|
|
54
|
+
body { font-family: var(--font-display); background: var(--bg-primary); color: var(--text-primary); }
|
|
55
|
+
|
|
56
|
+
.slide {
|
|
57
|
+
width: 100vw;
|
|
58
|
+
height: 100vh;
|
|
59
|
+
height: 100dvh;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
scroll-snap-align: start;
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
position: relative;
|
|
66
|
+
padding: var(--slide-padding);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.slide-content {
|
|
70
|
+
flex: 1;
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
max-height: 100%;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
gap: var(--content-gap);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
h1 { font-size: var(--title-size); font-weight: 900; letter-spacing: -0.03em; line-height: 1.05; }
|
|
80
|
+
h2 { font-size: var(--h2-size); font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
|
|
81
|
+
h3 { font-size: var(--h3-size); font-weight: 700; line-height: 1.2; }
|
|
82
|
+
p, li { font-size: var(--body-size); line-height: 1.5; color: var(--text-secondary); }
|
|
83
|
+
|
|
84
|
+
.accent { color: var(--accent); }
|
|
85
|
+
.blue { color: var(--blue); }
|
|
86
|
+
.cyan { color: var(--cyan); }
|
|
87
|
+
.muted { color: var(--text-muted); }
|
|
88
|
+
.purple { color: var(--purple); }
|
|
89
|
+
|
|
90
|
+
/* Code blocks */
|
|
91
|
+
.code-block {
|
|
92
|
+
background: var(--code-bg);
|
|
93
|
+
border: 1px solid var(--border);
|
|
94
|
+
border-radius: 12px;
|
|
95
|
+
padding: clamp(0.75rem, 2vw, 1.5rem);
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
position: relative;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.code-block::before {
|
|
101
|
+
content: '';
|
|
102
|
+
position: absolute;
|
|
103
|
+
top: 0; left: 0; right: 0;
|
|
104
|
+
height: 1px;
|
|
105
|
+
background: linear-gradient(90deg, transparent, var(--cyan-glow), transparent);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.code-block pre {
|
|
109
|
+
font-family: var(--font-mono);
|
|
110
|
+
font-size: var(--code-size);
|
|
111
|
+
line-height: 1.6;
|
|
112
|
+
color: var(--text-secondary);
|
|
113
|
+
white-space: pre;
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.code-block .comment { color: var(--text-muted); }
|
|
118
|
+
.code-block .keyword { color: var(--blue); }
|
|
119
|
+
.code-block .string { color: var(--green); }
|
|
120
|
+
.code-block .property { color: var(--accent); }
|
|
121
|
+
.code-block .method { color: var(--purple); }
|
|
122
|
+
.code-block .type { color: var(--cyan); }
|
|
123
|
+
.code-block .number { color: var(--orange); }
|
|
124
|
+
|
|
125
|
+
.tagline {
|
|
126
|
+
font-family: var(--font-mono);
|
|
127
|
+
font-size: var(--small-size);
|
|
128
|
+
color: var(--cyan);
|
|
129
|
+
padding-top: clamp(0.5rem, 1.5vw, 1.25rem);
|
|
130
|
+
border-top: 1px solid var(--border);
|
|
131
|
+
letter-spacing: 0.02em;
|
|
132
|
+
margin-top: auto;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Animations */
|
|
136
|
+
.reveal {
|
|
137
|
+
opacity: 0;
|
|
138
|
+
transform: translateY(24px);
|
|
139
|
+
transition: opacity 0.7s var(--ease-out-expo), transform 0.7s var(--ease-out-expo);
|
|
140
|
+
}
|
|
141
|
+
.slide.visible .reveal { opacity: 1; transform: translateY(0); }
|
|
142
|
+
.reveal-delay-1 { transition-delay: 0.08s; }
|
|
143
|
+
.reveal-delay-2 { transition-delay: 0.16s; }
|
|
144
|
+
.reveal-delay-3 { transition-delay: 0.24s; }
|
|
145
|
+
.reveal-delay-4 { transition-delay: 0.32s; }
|
|
146
|
+
.reveal-delay-5 { transition-delay: 0.40s; }
|
|
147
|
+
|
|
148
|
+
.reveal-scale {
|
|
149
|
+
opacity: 0; transform: scale(0.92);
|
|
150
|
+
transition: opacity 0.7s var(--ease-out-expo), transform 0.7s var(--ease-out-expo);
|
|
151
|
+
}
|
|
152
|
+
.slide.visible .reveal-scale { opacity: 1; transform: scale(1); }
|
|
153
|
+
|
|
154
|
+
/* Progress + nav */
|
|
155
|
+
.progress-bar {
|
|
156
|
+
position: fixed; top: 0; left: 0; height: 2px;
|
|
157
|
+
background: var(--cyan); z-index: 100;
|
|
158
|
+
transition: width 0.3s ease;
|
|
159
|
+
box-shadow: 0 0 10px var(--cyan-glow);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.nav-dots {
|
|
163
|
+
position: fixed; right: clamp(0.75rem, 2vw, 1.5rem);
|
|
164
|
+
top: 50%; transform: translateY(-50%);
|
|
165
|
+
display: flex; flex-direction: column; gap: 8px; z-index: 100;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.nav-dot {
|
|
169
|
+
width: 6px; height: 6px; border-radius: 50%;
|
|
170
|
+
background: var(--text-muted); cursor: pointer;
|
|
171
|
+
transition: all 0.3s ease; border: none; padding: 0;
|
|
172
|
+
}
|
|
173
|
+
.nav-dot.active { background: var(--cyan); box-shadow: 0 0 8px var(--cyan-glow); transform: scale(1.4); }
|
|
174
|
+
.nav-dot:hover { background: var(--text-secondary); transform: scale(1.3); }
|
|
175
|
+
|
|
176
|
+
.slide-num {
|
|
177
|
+
position: absolute;
|
|
178
|
+
bottom: clamp(0.75rem, 2vw, 1.5rem);
|
|
179
|
+
right: clamp(0.75rem, 2vw, 1.5rem);
|
|
180
|
+
font-family: var(--font-mono);
|
|
181
|
+
font-size: clamp(0.55rem, 0.8vw, 0.7rem);
|
|
182
|
+
color: var(--text-muted);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.grid-bg {
|
|
186
|
+
position: absolute; inset: 0; pointer-events: none;
|
|
187
|
+
background-image:
|
|
188
|
+
linear-gradient(rgba(255,255,255,0.012) 1px, transparent 1px),
|
|
189
|
+
linear-gradient(90deg, rgba(255,255,255,0.012) 1px, transparent 1px);
|
|
190
|
+
background-size: 60px 60px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Title slide */
|
|
194
|
+
.title-slide { text-align: center; align-items: center; }
|
|
195
|
+
.title-slide .slide-content { align-items: center; max-width: 950px; }
|
|
196
|
+
|
|
197
|
+
.title-sub {
|
|
198
|
+
font-family: var(--font-mono);
|
|
199
|
+
font-size: var(--small-size);
|
|
200
|
+
color: var(--text-muted);
|
|
201
|
+
letter-spacing: 0.15em;
|
|
202
|
+
text-transform: uppercase;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.title-bottom {
|
|
206
|
+
font-family: var(--font-mono);
|
|
207
|
+
font-size: var(--small-size);
|
|
208
|
+
color: var(--text-muted);
|
|
209
|
+
margin-top: auto;
|
|
210
|
+
padding-top: clamp(0.5rem, 1.5vw, 1rem);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Bullet list */
|
|
214
|
+
.bullet-list {
|
|
215
|
+
list-style: none;
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-direction: column;
|
|
218
|
+
gap: clamp(0.5rem, 1.2vh, 1rem);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.bullet-list li {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: flex-start;
|
|
224
|
+
gap: clamp(0.5rem, 1vw, 1rem);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.bullet-icon {
|
|
228
|
+
flex-shrink: 0;
|
|
229
|
+
width: clamp(1.25rem, 2vw, 1.75rem);
|
|
230
|
+
height: clamp(1.25rem, 2vw, 1.75rem);
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
justify-content: center;
|
|
234
|
+
font-size: clamp(0.75rem, 1.1vw, 1rem);
|
|
235
|
+
margin-top: 0.15em;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Two column layout */
|
|
239
|
+
.two-col {
|
|
240
|
+
display: grid;
|
|
241
|
+
grid-template-columns: 1fr 1fr;
|
|
242
|
+
gap: clamp(0.75rem, 2vw, 1.5rem);
|
|
243
|
+
align-items: start;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.col-label {
|
|
247
|
+
font-family: var(--font-mono);
|
|
248
|
+
font-size: var(--small-size);
|
|
249
|
+
font-weight: 700;
|
|
250
|
+
text-transform: uppercase;
|
|
251
|
+
letter-spacing: 0.08em;
|
|
252
|
+
margin-bottom: clamp(0.25rem, 0.5vh, 0.5rem);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* Flow diagram */
|
|
256
|
+
.flow {
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
gap: clamp(0.3rem, 0.8vw, 0.6rem);
|
|
260
|
+
flex-wrap: wrap;
|
|
261
|
+
justify-content: center;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.flow-step {
|
|
265
|
+
background: var(--bg-card);
|
|
266
|
+
border: 1px solid var(--border);
|
|
267
|
+
border-radius: 8px;
|
|
268
|
+
padding: clamp(0.3rem, 0.7vw, 0.5rem) clamp(0.5rem, 1vw, 0.8rem);
|
|
269
|
+
font-family: var(--font-mono);
|
|
270
|
+
font-size: var(--small-size);
|
|
271
|
+
color: var(--text-secondary);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.flow-step.highlight {
|
|
275
|
+
border-color: rgba(34, 211, 238, 0.3);
|
|
276
|
+
color: var(--cyan);
|
|
277
|
+
box-shadow: 0 0 12px rgba(34, 211, 238, 0.08);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.flow-arrow {
|
|
281
|
+
color: var(--text-muted);
|
|
282
|
+
font-size: var(--small-size);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* Feature cards for tool surface */
|
|
286
|
+
.tool-grid {
|
|
287
|
+
display: grid;
|
|
288
|
+
grid-template-columns: repeat(2, 1fr);
|
|
289
|
+
gap: clamp(0.4rem, 1vw, 0.75rem);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.tool-card {
|
|
293
|
+
background: var(--bg-card);
|
|
294
|
+
border: 1px solid var(--border);
|
|
295
|
+
border-radius: 10px;
|
|
296
|
+
padding: clamp(0.5rem, 1.2vw, 1rem);
|
|
297
|
+
display: flex;
|
|
298
|
+
flex-direction: column;
|
|
299
|
+
gap: clamp(0.15rem, 0.4vh, 0.3rem);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.tool-card h3 {
|
|
303
|
+
font-family: var(--font-mono);
|
|
304
|
+
font-size: var(--small-size);
|
|
305
|
+
color: var(--cyan);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.tool-card p {
|
|
309
|
+
font-size: clamp(0.6rem, 0.9vw, 0.8rem);
|
|
310
|
+
color: var(--text-muted);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Trust visual */
|
|
314
|
+
.trust-row {
|
|
315
|
+
display: flex;
|
|
316
|
+
align-items: center;
|
|
317
|
+
gap: clamp(0.75rem, 2vw, 1.5rem);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.trust-bar {
|
|
321
|
+
flex: 1;
|
|
322
|
+
height: clamp(2rem, 4vh, 3rem);
|
|
323
|
+
border-radius: 6px;
|
|
324
|
+
position: relative;
|
|
325
|
+
overflow: hidden;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.trust-bar-fill {
|
|
329
|
+
height: 100%;
|
|
330
|
+
border-radius: 6px;
|
|
331
|
+
display: flex;
|
|
332
|
+
align-items: center;
|
|
333
|
+
padding-left: clamp(0.5rem, 1vw, 1rem);
|
|
334
|
+
font-family: var(--font-mono);
|
|
335
|
+
font-size: clamp(0.6rem, 0.9vw, 0.75rem);
|
|
336
|
+
font-weight: 600;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.trust-label {
|
|
340
|
+
font-size: var(--small-size);
|
|
341
|
+
color: var(--text-secondary);
|
|
342
|
+
white-space: nowrap;
|
|
343
|
+
min-width: clamp(4rem, 8vw, 7rem);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Closing */
|
|
347
|
+
.closing-slide { text-align: center; align-items: center; }
|
|
348
|
+
.closing-slide .slide-content { align-items: center; }
|
|
349
|
+
|
|
350
|
+
.closing-install {
|
|
351
|
+
font-family: var(--font-mono);
|
|
352
|
+
font-size: var(--h3-size);
|
|
353
|
+
color: var(--cyan);
|
|
354
|
+
background: rgba(34, 211, 238, 0.06);
|
|
355
|
+
padding: 0.4em 1.2em;
|
|
356
|
+
border-radius: 8px;
|
|
357
|
+
border: 1px solid rgba(34, 211, 238, 0.15);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.closing-link {
|
|
361
|
+
font-family: var(--font-mono);
|
|
362
|
+
font-size: var(--body-size);
|
|
363
|
+
color: var(--blue);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Conversation diagram */
|
|
367
|
+
.convo {
|
|
368
|
+
display: flex;
|
|
369
|
+
flex-direction: column;
|
|
370
|
+
gap: clamp(0.3rem, 0.8vh, 0.5rem);
|
|
371
|
+
max-width: 650px;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.convo-msg {
|
|
375
|
+
display: flex;
|
|
376
|
+
gap: clamp(0.4rem, 0.8vw, 0.6rem);
|
|
377
|
+
align-items: flex-start;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.convo-who {
|
|
381
|
+
font-family: var(--font-mono);
|
|
382
|
+
font-size: clamp(0.55rem, 0.85vw, 0.7rem);
|
|
383
|
+
font-weight: 700;
|
|
384
|
+
padding: 0.2em 0.6em;
|
|
385
|
+
border-radius: 4px;
|
|
386
|
+
white-space: nowrap;
|
|
387
|
+
margin-top: 0.15em;
|
|
388
|
+
flex-shrink: 0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.convo-who.ai {
|
|
392
|
+
background: rgba(34, 211, 238, 0.1);
|
|
393
|
+
color: var(--cyan);
|
|
394
|
+
border: 1px solid rgba(34, 211, 238, 0.2);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.convo-who.human {
|
|
398
|
+
background: var(--accent-dim);
|
|
399
|
+
color: var(--accent);
|
|
400
|
+
border: 1px solid rgba(232, 166, 52, 0.2);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.convo-text {
|
|
404
|
+
font-family: var(--font-mono);
|
|
405
|
+
font-size: var(--small-size);
|
|
406
|
+
color: var(--text-secondary);
|
|
407
|
+
line-height: 1.5;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.convo-text code {
|
|
411
|
+
color: var(--green);
|
|
412
|
+
font-size: inherit;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* Shared map visual */
|
|
416
|
+
.shared-map {
|
|
417
|
+
display: grid;
|
|
418
|
+
grid-template-columns: 1fr auto 1fr;
|
|
419
|
+
gap: clamp(0.5rem, 1.2vw, 1rem);
|
|
420
|
+
align-items: center;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.map-side {
|
|
424
|
+
display: flex;
|
|
425
|
+
flex-direction: column;
|
|
426
|
+
gap: clamp(0.3rem, 0.6vh, 0.4rem);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.map-side-label {
|
|
430
|
+
font-family: var(--font-mono);
|
|
431
|
+
font-size: var(--small-size);
|
|
432
|
+
font-weight: 700;
|
|
433
|
+
letter-spacing: 0.08em;
|
|
434
|
+
text-transform: uppercase;
|
|
435
|
+
margin-bottom: clamp(0.15rem, 0.4vh, 0.3rem);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.map-item {
|
|
439
|
+
font-size: clamp(0.6rem, 0.9vw, 0.8rem);
|
|
440
|
+
color: var(--text-secondary);
|
|
441
|
+
display: flex;
|
|
442
|
+
align-items: center;
|
|
443
|
+
gap: 0.4em;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.map-center {
|
|
447
|
+
display: flex;
|
|
448
|
+
flex-direction: column;
|
|
449
|
+
align-items: center;
|
|
450
|
+
gap: clamp(0.25rem, 0.5vh, 0.4rem);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.map-container-box {
|
|
454
|
+
background: var(--bg-card);
|
|
455
|
+
border: 1px solid var(--accent);
|
|
456
|
+
border-radius: 10px;
|
|
457
|
+
padding: clamp(0.6rem, 1.2vw, 1rem) clamp(0.8rem, 1.5vw, 1.25rem);
|
|
458
|
+
text-align: center;
|
|
459
|
+
box-shadow: 0 0 20px var(--accent-dim);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.map-container-title {
|
|
463
|
+
font-family: var(--font-mono);
|
|
464
|
+
font-size: var(--h3-size);
|
|
465
|
+
font-weight: 700;
|
|
466
|
+
color: var(--accent);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.map-container-desc {
|
|
470
|
+
font-size: clamp(0.55rem, 0.8vw, 0.7rem);
|
|
471
|
+
color: var(--text-muted);
|
|
472
|
+
margin-top: 0.2em;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.map-arrow {
|
|
476
|
+
color: var(--text-muted);
|
|
477
|
+
font-size: clamp(1rem, 1.5vw, 1.25rem);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/* Responsive */
|
|
481
|
+
@media (max-height: 700px) {
|
|
482
|
+
:root {
|
|
483
|
+
--slide-padding: clamp(1rem, 3vw, 2.5rem);
|
|
484
|
+
--content-gap: clamp(0.5rem, 1.5vw, 1rem);
|
|
485
|
+
--title-size: clamp(1.5rem, 5vw, 3rem);
|
|
486
|
+
--h2-size: clamp(1.25rem, 3.5vw, 2rem);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
@media (max-height: 600px) {
|
|
491
|
+
:root {
|
|
492
|
+
--slide-padding: clamp(0.75rem, 2.5vw, 1.5rem);
|
|
493
|
+
--content-gap: clamp(0.4rem, 1vw, 0.75rem);
|
|
494
|
+
--title-size: clamp(1.25rem, 4.5vw, 2.5rem);
|
|
495
|
+
--body-size: clamp(0.7rem, 1.2vw, 0.95rem);
|
|
496
|
+
}
|
|
497
|
+
.nav-dots { display: none; }
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
@media (max-height: 500px) {
|
|
501
|
+
:root {
|
|
502
|
+
--slide-padding: clamp(0.5rem, 2vw, 1rem);
|
|
503
|
+
--title-size: clamp(1rem, 3.5vw, 1.75rem);
|
|
504
|
+
--h2-size: clamp(0.9rem, 2.5vw, 1.25rem);
|
|
505
|
+
--body-size: clamp(0.65rem, 1vw, 0.85rem);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
@media (max-width: 600px) {
|
|
510
|
+
.two-col, .tool-grid, .shared-map { grid-template-columns: 1fr; }
|
|
511
|
+
.map-arrow { transform: rotate(90deg); }
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
@media (prefers-reduced-motion: reduce) {
|
|
515
|
+
*, *::before, *::after {
|
|
516
|
+
animation-duration: 0.01ms !important;
|
|
517
|
+
transition-duration: 0.2s !important;
|
|
518
|
+
}
|
|
519
|
+
html { scroll-behavior: auto; }
|
|
520
|
+
}
|
|
521
|
+
</style>
|
|
522
|
+
</head>
|
|
523
|
+
<body>
|
|
524
|
+
|
|
525
|
+
<div class="progress-bar" id="progress"></div>
|
|
526
|
+
<nav class="nav-dots" id="navDots"></nav>
|
|
527
|
+
|
|
528
|
+
<!-- ============================================
|
|
529
|
+
SLIDE 1: TITLE
|
|
530
|
+
============================================ -->
|
|
531
|
+
<section class="slide title-slide" data-slide="0">
|
|
532
|
+
<div class="grid-bg"></div>
|
|
533
|
+
<div class="slide-content">
|
|
534
|
+
<p class="title-sub reveal">Part 2 — The AI-Native Architecture</p>
|
|
535
|
+
<h1 class="reveal reveal-delay-1">The Container<br>That <span class="cyan">Teaches Itself</span></h1>
|
|
536
|
+
<p class="title-bottom reveal reveal-delay-2">when your codebase is the prompt</p>
|
|
537
|
+
</div>
|
|
538
|
+
</section>
|
|
539
|
+
|
|
540
|
+
<!-- ============================================
|
|
541
|
+
SLIDE 2: THE PROBLEM WITH AI + CODE
|
|
542
|
+
============================================ -->
|
|
543
|
+
<section class="slide" data-slide="1">
|
|
544
|
+
<div class="grid-bg"></div>
|
|
545
|
+
<div class="slide-content">
|
|
546
|
+
<h2 class="reveal">AI Writes Code.<br><span class="muted">But Whose Architecture?</span></h2>
|
|
547
|
+
<ul class="bullet-list">
|
|
548
|
+
<li class="reveal reveal-delay-1">
|
|
549
|
+
<span class="bullet-icon">💥</span>
|
|
550
|
+
<span>AI generates sprawling, unstructured code every time you ask</span>
|
|
551
|
+
</li>
|
|
552
|
+
<li class="reveal reveal-delay-2">
|
|
553
|
+
<span class="bullet-icon">🔍</span>
|
|
554
|
+
<span>You spend more time reviewing AI output than you saved writing it</span>
|
|
555
|
+
</li>
|
|
556
|
+
<li class="reveal reveal-delay-3">
|
|
557
|
+
<span class="bullet-icon">🎭</span>
|
|
558
|
+
<span>The more AI writes, the less you trust what's in there</span>
|
|
559
|
+
</li>
|
|
560
|
+
</ul>
|
|
561
|
+
<div class="tagline reveal reveal-delay-4">The problem isn't AI's code. It's that AI has no map.</div>
|
|
562
|
+
</div>
|
|
563
|
+
<span class="slide-num">02</span>
|
|
564
|
+
</section>
|
|
565
|
+
|
|
566
|
+
<!-- ============================================
|
|
567
|
+
SLIDE 3: INTROSPECTION
|
|
568
|
+
============================================ -->
|
|
569
|
+
<section class="slide" data-slide="2">
|
|
570
|
+
<div class="grid-bg"></div>
|
|
571
|
+
<div class="slide-content">
|
|
572
|
+
<h2 class="reveal">Everything Describes Itself</h2>
|
|
573
|
+
<div class="code-block reveal-scale reveal-delay-1">
|
|
574
|
+
<pre><span class="comment">// Any helper can explain itself at runtime</span>
|
|
575
|
+
<span class="keyword">const</span> fs = <span class="property">container</span>.<span class="method">feature</span>(<span class="string">'fs'</span>)
|
|
576
|
+
|
|
577
|
+
fs.<span class="method">introspect</span>() <span class="comment">// full API: methods, state shape, events</span>
|
|
578
|
+
fs.<span class="method">introspectAsText</span>() <span class="comment">// human-readable docs</span>
|
|
579
|
+
fs.<span class="method">introspectAsType</span>() <span class="comment">// TypeScript interface</span>
|
|
580
|
+
|
|
581
|
+
<span class="comment">// Discover everything available</span>
|
|
582
|
+
<span class="property">container</span>.<span class="method">features</span>.<span class="property">available</span> <span class="comment">// what exists</span>
|
|
583
|
+
<span class="property">container</span>.<span class="method">features</span>.<span class="method">describe</span>() <span class="comment">// what each one does</span></pre>
|
|
584
|
+
</div>
|
|
585
|
+
<div class="tagline reveal reveal-delay-2">Know the philosophy. The container teaches you the rest.</div>
|
|
586
|
+
</div>
|
|
587
|
+
<span class="slide-num">03</span>
|
|
588
|
+
</section>
|
|
589
|
+
|
|
590
|
+
<!-- ============================================
|
|
591
|
+
SLIDE 4: AI AGENT DISCOVERS THE CONTAINER
|
|
592
|
+
============================================ -->
|
|
593
|
+
<section class="slide" data-slide="3">
|
|
594
|
+
<div class="grid-bg"></div>
|
|
595
|
+
<div class="slide-content">
|
|
596
|
+
<h2 class="reveal">An Agent Walks Into a Container</h2>
|
|
597
|
+
<div class="convo">
|
|
598
|
+
<div class="convo-msg reveal reveal-delay-1">
|
|
599
|
+
<span class="convo-who ai">AGENT</span>
|
|
600
|
+
<span class="convo-text"><code>container.features.available</code></span>
|
|
601
|
+
</div>
|
|
602
|
+
<div class="convo-msg reveal reveal-delay-2">
|
|
603
|
+
<span class="convo-who human">LUCA</span>
|
|
604
|
+
<span class="convo-text">['fs', 'git', 'proc', 'ui', 'networking', 'grep', ...]</span>
|
|
605
|
+
</div>
|
|
606
|
+
<div class="convo-msg reveal reveal-delay-3">
|
|
607
|
+
<span class="convo-who ai">AGENT</span>
|
|
608
|
+
<span class="convo-text"><code>container.feature('git').introspect()</code></span>
|
|
609
|
+
</div>
|
|
610
|
+
<div class="convo-msg reveal reveal-delay-4">
|
|
611
|
+
<span class="convo-who human">LUCA</span>
|
|
612
|
+
<span class="convo-text">{ methods: [branch, sha, lsFiles, ...], state: { branch, sha, isRepo }, events: [...] }</span>
|
|
613
|
+
</div>
|
|
614
|
+
<div class="convo-msg reveal reveal-delay-5">
|
|
615
|
+
<span class="convo-who ai">AGENT</span>
|
|
616
|
+
<span class="convo-text"><code>container.git.branch</code> → writes code against it</span>
|
|
617
|
+
</div>
|
|
618
|
+
</div>
|
|
619
|
+
<div class="tagline reveal reveal-delay-5">No docs needed. No training data. The runtime IS the documentation.</div>
|
|
620
|
+
</div>
|
|
621
|
+
<span class="slide-num">04</span>
|
|
622
|
+
</section>
|
|
623
|
+
|
|
624
|
+
<!-- ============================================
|
|
625
|
+
SLIDE 5: EVERY HELPER IS A TOOL
|
|
626
|
+
============================================ -->
|
|
627
|
+
<section class="slide" data-slide="4">
|
|
628
|
+
<div class="grid-bg"></div>
|
|
629
|
+
<div class="slide-content">
|
|
630
|
+
<h2 class="reveal">Every Helper Is a Tool Surface</h2>
|
|
631
|
+
<div class="code-block reveal-scale reveal-delay-1">
|
|
632
|
+
<pre><span class="comment">// Any feature can expose itself to an AI assistant</span>
|
|
633
|
+
<span class="keyword">const</span> git = <span class="property">container</span>.<span class="method">feature</span>(<span class="string">'git'</span>)
|
|
634
|
+
<span class="keyword">const</span> { <span class="property">schemas</span>, <span class="property">handlers</span> } = git.<span class="method">toTools</span>()
|
|
635
|
+
|
|
636
|
+
<span class="comment">// schemas → OpenAI-compatible function definitions</span>
|
|
637
|
+
<span class="comment">// handlers → the actual implementations</span>
|
|
638
|
+
|
|
639
|
+
<span class="comment">// Give an assistant access to any feature</span>
|
|
640
|
+
assistant.<span class="method">use</span>(<span class="property">container</span>.<span class="method">feature</span>(<span class="string">'fs'</span>))
|
|
641
|
+
assistant.<span class="method">use</span>(<span class="property">container</span>.<span class="method">feature</span>(<span class="string">'git'</span>))
|
|
642
|
+
assistant.<span class="method">use</span>(<span class="property">container</span>.<span class="method">feature</span>(<span class="string">'proc'</span>))</pre>
|
|
643
|
+
</div>
|
|
644
|
+
<div class="tagline reveal reveal-delay-2">Build the feature once. Expose it to AI with one line.</div>
|
|
645
|
+
</div>
|
|
646
|
+
<span class="slide-num">05</span>
|
|
647
|
+
</section>
|
|
648
|
+
|
|
649
|
+
<!-- ============================================
|
|
650
|
+
SLIDE 6: THE ASSISTANT SYSTEM
|
|
651
|
+
============================================ -->
|
|
652
|
+
<section class="slide" data-slide="5">
|
|
653
|
+
<div class="grid-bg"></div>
|
|
654
|
+
<div class="slide-content">
|
|
655
|
+
<h2 class="reveal">Assistants Are Just Folders</h2>
|
|
656
|
+
<div class="two-col">
|
|
657
|
+
<div class="reveal reveal-delay-1">
|
|
658
|
+
<div class="col-label accent">Structure</div>
|
|
659
|
+
<div class="code-block">
|
|
660
|
+
<pre class="dir-tree" style="font-size:var(--small-size)"><span style="color:var(--blue);font-weight:600">assistants/researcher/</span>
|
|
661
|
+
├── <span style="color:var(--accent)">CORE.md</span> <span style="color:var(--text-muted)">system prompt</span>
|
|
662
|
+
├── <span style="color:var(--accent)">tools.ts</span> <span style="color:var(--text-muted)">Zod-schema tools</span>
|
|
663
|
+
├── <span style="color:var(--accent)">hooks.ts</span> <span style="color:var(--text-muted)">lifecycle hooks</span>
|
|
664
|
+
└── <span style="color:var(--blue);font-weight:600">docs/</span> <span style="color:var(--text-muted)">auto-injected context</span></pre>
|
|
665
|
+
</div>
|
|
666
|
+
</div>
|
|
667
|
+
<div class="reveal reveal-delay-2">
|
|
668
|
+
<div class="col-label cyan">Usage</div>
|
|
669
|
+
<div class="code-block">
|
|
670
|
+
<pre><span class="keyword">const</span> asst = <span class="property">container</span>
|
|
671
|
+
.<span class="method">feature</span>(<span class="string">'assistant'</span>)
|
|
672
|
+
|
|
673
|
+
<span class="comment">// Give it any feature as tools</span>
|
|
674
|
+
asst.<span class="method">use</span>(<span class="property">container</span>.<span class="method">feature</span>(<span class="string">'fs'</span>))
|
|
675
|
+
asst.<span class="method">use</span>(<span class="property">container</span>.<span class="method">feature</span>(<span class="string">'git'</span>))
|
|
676
|
+
|
|
677
|
+
<span class="keyword">const</span> reply = <span class="keyword">await</span> asst.<span class="method">ask</span>(
|
|
678
|
+
<span class="string">'What changed this week?'</span>
|
|
679
|
+
)</pre>
|
|
680
|
+
</div>
|
|
681
|
+
</div>
|
|
682
|
+
</div>
|
|
683
|
+
<div class="tagline reveal reveal-delay-3">assistant.use(anyFeature) — that's the whole integration story.</div>
|
|
684
|
+
</div>
|
|
685
|
+
<span class="slide-num">06</span>
|
|
686
|
+
</section>
|
|
687
|
+
|
|
688
|
+
<!-- ============================================
|
|
689
|
+
SLIDE 7: THE SHARED MENTAL MODEL
|
|
690
|
+
============================================ -->
|
|
691
|
+
<section class="slide" data-slide="6">
|
|
692
|
+
<div class="grid-bg"></div>
|
|
693
|
+
<div class="slide-content">
|
|
694
|
+
<h2 class="reveal">One Map. Two Navigators.</h2>
|
|
695
|
+
<div class="shared-map reveal reveal-delay-1">
|
|
696
|
+
<div class="map-side">
|
|
697
|
+
<div class="map-side-label accent">Human Defines</div>
|
|
698
|
+
<div class="map-item">🏗 The architecture</div>
|
|
699
|
+
<div class="map-item">📋 Helper interfaces</div>
|
|
700
|
+
<div class="map-item">📁 Where things live</div>
|
|
701
|
+
<div class="map-item">🏷 What categories exist</div>
|
|
702
|
+
</div>
|
|
703
|
+
<div class="map-center">
|
|
704
|
+
<span class="map-arrow">←</span>
|
|
705
|
+
<div class="map-container-box">
|
|
706
|
+
<div class="map-container-title">container</div>
|
|
707
|
+
<div class="map-container-desc">shared mental model</div>
|
|
708
|
+
</div>
|
|
709
|
+
<span class="map-arrow">→</span>
|
|
710
|
+
</div>
|
|
711
|
+
<div class="map-side">
|
|
712
|
+
<div class="map-side-label cyan">AI Implements</div>
|
|
713
|
+
<div class="map-item">⚙ Helper internals</div>
|
|
714
|
+
<div class="map-item">🧪 Tests and validation</div>
|
|
715
|
+
<div class="map-item">🔄 Composition logic</div>
|
|
716
|
+
<div class="map-item">🔨 The boring stuff</div>
|
|
717
|
+
</div>
|
|
718
|
+
</div>
|
|
719
|
+
<div class="tagline reveal reveal-delay-2">You design the map. AI respects it. The codebase stays yours.</div>
|
|
720
|
+
</div>
|
|
721
|
+
<span class="slide-num">07</span>
|
|
722
|
+
</section>
|
|
723
|
+
|
|
724
|
+
<!-- ============================================
|
|
725
|
+
SLIDE 8: TRUST THROUGH COMPOSITION
|
|
726
|
+
============================================ -->
|
|
727
|
+
<section class="slide" data-slide="7">
|
|
728
|
+
<div class="grid-bg"></div>
|
|
729
|
+
<div class="slide-content">
|
|
730
|
+
<h2 class="reveal">More AI Code = <span class="cyan">More Trust</span></h2>
|
|
731
|
+
<p class="reveal reveal-delay-1" style="max-width:600px">Normally, the more AI writes, the less confident you feel. With Luca, AI composes with helpers you've already reviewed. New code gets captured into new helpers. The codebase grows <em>more</em> trustworthy.</p>
|
|
732
|
+
<div style="display:flex;flex-direction:column;gap:clamp(0.4rem,1vh,0.75rem)">
|
|
733
|
+
<div class="trust-row reveal reveal-delay-2">
|
|
734
|
+
<span class="trust-label">Week 1</span>
|
|
735
|
+
<div class="trust-bar" style="background:var(--bg-card);border:1px solid var(--border)">
|
|
736
|
+
<div class="trust-bar-fill" style="width:30%;background:linear-gradient(90deg,rgba(34,211,238,0.3),rgba(34,211,238,0.15));color:var(--cyan)">reviewed</div>
|
|
737
|
+
</div>
|
|
738
|
+
</div>
|
|
739
|
+
<div class="trust-row reveal reveal-delay-3">
|
|
740
|
+
<span class="trust-label">Month 1</span>
|
|
741
|
+
<div class="trust-bar" style="background:var(--bg-card);border:1px solid var(--border)">
|
|
742
|
+
<div class="trust-bar-fill" style="width:65%;background:linear-gradient(90deg,rgba(34,211,238,0.3),rgba(34,211,238,0.15));color:var(--cyan)">reviewed</div>
|
|
743
|
+
</div>
|
|
744
|
+
</div>
|
|
745
|
+
<div class="trust-row reveal reveal-delay-4">
|
|
746
|
+
<span class="trust-label">Month 6</span>
|
|
747
|
+
<div class="trust-bar" style="background:var(--bg-card);border:1px solid var(--border)">
|
|
748
|
+
<div class="trust-bar-fill" style="width:90%;background:linear-gradient(90deg,rgba(34,211,238,0.3),rgba(34,211,238,0.15));color:var(--cyan)">reviewed</div>
|
|
749
|
+
</div>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
<div class="tagline reveal reveal-delay-5">The surface area of unreviewed code shrinks because AI reaches for existing helpers.</div>
|
|
753
|
+
</div>
|
|
754
|
+
<span class="slide-num">08</span>
|
|
755
|
+
</section>
|
|
756
|
+
|
|
757
|
+
<!-- ============================================
|
|
758
|
+
SLIDE 9: OBSERVABLE BY DEFAULT
|
|
759
|
+
============================================ -->
|
|
760
|
+
<section class="slide" data-slide="8">
|
|
761
|
+
<div class="grid-bg"></div>
|
|
762
|
+
<div class="slide-content">
|
|
763
|
+
<h2 class="reveal">Agents Can Watch Everything</h2>
|
|
764
|
+
<div class="code-block reveal-scale reveal-delay-1">
|
|
765
|
+
<pre><span class="comment">// An agent monitors the system in real-time</span>
|
|
766
|
+
<span class="property">container</span>.<span class="method">on</span>(<span class="string">'featureEnabled'</span>, (<span class="property">id</span>) => {
|
|
767
|
+
agent.<span class="method">log</span>(<span class="string">`Feature ${id} came online`</span>)
|
|
768
|
+
})
|
|
769
|
+
|
|
770
|
+
server.<span class="method">state</span>.<span class="method">observe</span>((<span class="property">type</span>, <span class="property">key</span>, <span class="property">val</span>) => {
|
|
771
|
+
<span class="keyword">if</span> (key === <span class="string">'requestCount'</span> && val > <span class="number">1000</span>)
|
|
772
|
+
agent.<span class="method">alert</span>(<span class="string">'Traffic spike detected'</span>)
|
|
773
|
+
})
|
|
774
|
+
|
|
775
|
+
<span class="comment">// Same primitives that power the UI, power the agent</span></pre>
|
|
776
|
+
</div>
|
|
777
|
+
<div class="tagline reveal reveal-delay-2">Observable state + events = AI can monitor, react, and intervene.</div>
|
|
778
|
+
</div>
|
|
779
|
+
<span class="slide-num">09</span>
|
|
780
|
+
</section>
|
|
781
|
+
|
|
782
|
+
<!-- ============================================
|
|
783
|
+
SLIDE 10: THE REPL-TO-AGENT PIPELINE
|
|
784
|
+
============================================ -->
|
|
785
|
+
<section class="slide" data-slide="9">
|
|
786
|
+
<div class="grid-bg"></div>
|
|
787
|
+
<div class="slide-content">
|
|
788
|
+
<h2 class="reveal">REPL-Friendly = Agent-Friendly</h2>
|
|
789
|
+
<div class="tool-grid">
|
|
790
|
+
<div class="tool-card reveal reveal-delay-1">
|
|
791
|
+
<h3>Discoverability</h3>
|
|
792
|
+
<p>What's available? What can it do? Ask and the container answers.</p>
|
|
793
|
+
</div>
|
|
794
|
+
<div class="tool-card reveal reveal-delay-2">
|
|
795
|
+
<h3>Introspection</h3>
|
|
796
|
+
<p>Every method, every event, every state shape — queryable at runtime.</p>
|
|
797
|
+
</div>
|
|
798
|
+
<div class="tool-card reveal reveal-delay-3">
|
|
799
|
+
<h3>Observable State</h3>
|
|
800
|
+
<p>Watch anything change. React without polling. Same as React, but headless.</p>
|
|
801
|
+
</div>
|
|
802
|
+
<div class="tool-card reveal reveal-delay-4">
|
|
803
|
+
<h3>Immediate Feedback</h3>
|
|
804
|
+
<p>Run code, see results, iterate. The agent loop IS the REPL loop.</p>
|
|
805
|
+
</div>
|
|
806
|
+
</div>
|
|
807
|
+
<div class="tagline reveal reveal-delay-5">What makes something nice for a REPL is exactly what makes it nice for an agent.</div>
|
|
808
|
+
</div>
|
|
809
|
+
<span class="slide-num">10</span>
|
|
810
|
+
</section>
|
|
811
|
+
|
|
812
|
+
<!-- ============================================
|
|
813
|
+
SLIDE 11: CLOSING
|
|
814
|
+
============================================ -->
|
|
815
|
+
<section class="slide closing-slide" data-slide="10">
|
|
816
|
+
<div class="grid-bg"></div>
|
|
817
|
+
<div class="slide-content">
|
|
818
|
+
<h1 class="reveal">Your Codebase<br>Is the <span class="cyan">Prompt.</span></h1>
|
|
819
|
+
<div class="closing-install reveal reveal-delay-1">bun add @soederpop/luca</div>
|
|
820
|
+
<p class="closing-link reveal reveal-delay-2">github.com/soederpop/luca</p>
|
|
821
|
+
</div>
|
|
822
|
+
</section>
|
|
823
|
+
|
|
824
|
+
<script>
|
|
825
|
+
class SlidePresentation {
|
|
826
|
+
constructor() {
|
|
827
|
+
this.slides = document.querySelectorAll('.slide');
|
|
828
|
+
this.currentSlide = 0;
|
|
829
|
+
this.totalSlides = this.slides.length;
|
|
830
|
+
this.progressBar = document.getElementById('progress');
|
|
831
|
+
this.navContainer = document.getElementById('navDots');
|
|
832
|
+
|
|
833
|
+
this.createNavDots();
|
|
834
|
+
this.setupIntersectionObserver();
|
|
835
|
+
this.setupKeyboardNav();
|
|
836
|
+
this.updateProgress();
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
createNavDots() {
|
|
840
|
+
this.slides.forEach((_, i) => {
|
|
841
|
+
const dot = document.createElement('button');
|
|
842
|
+
dot.className = 'nav-dot' + (i === 0 ? ' active' : '');
|
|
843
|
+
dot.setAttribute('aria-label', `Go to slide ${i + 1}`);
|
|
844
|
+
dot.addEventListener('click', () => this.goToSlide(i));
|
|
845
|
+
this.navContainer.appendChild(dot);
|
|
846
|
+
});
|
|
847
|
+
this.dots = this.navContainer.querySelectorAll('.nav-dot');
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
setupIntersectionObserver() {
|
|
851
|
+
const observer = new IntersectionObserver((entries) => {
|
|
852
|
+
entries.forEach(entry => {
|
|
853
|
+
if (entry.isIntersecting) {
|
|
854
|
+
entry.target.classList.add('visible');
|
|
855
|
+
const index = parseInt(entry.target.dataset.slide);
|
|
856
|
+
if (!isNaN(index)) {
|
|
857
|
+
this.currentSlide = index;
|
|
858
|
+
this.updateProgress();
|
|
859
|
+
this.updateDots();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
}, { threshold: 0.5 });
|
|
864
|
+
|
|
865
|
+
this.slides.forEach(slide => observer.observe(slide));
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
setupKeyboardNav() {
|
|
869
|
+
document.addEventListener('keydown', (e) => {
|
|
870
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowRight' || e.key === ' ') {
|
|
871
|
+
e.preventDefault();
|
|
872
|
+
this.goToSlide(Math.min(this.currentSlide + 1, this.totalSlides - 1));
|
|
873
|
+
} else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
|
|
874
|
+
e.preventDefault();
|
|
875
|
+
this.goToSlide(Math.max(this.currentSlide - 1, 0));
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
goToSlide(index) {
|
|
881
|
+
this.slides[index].scrollIntoView({ behavior: 'smooth' });
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
updateProgress() {
|
|
885
|
+
const progress = ((this.currentSlide + 1) / this.totalSlides) * 100;
|
|
886
|
+
this.progressBar.style.width = progress + '%';
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
updateDots() {
|
|
890
|
+
this.dots.forEach((dot, i) => {
|
|
891
|
+
dot.classList.toggle('active', i === this.currentSlide);
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
897
|
+
new SlidePresentation();
|
|
898
|
+
});
|
|
899
|
+
</script>
|
|
900
|
+
|
|
901
|
+
</body>
|
|
902
|
+
</html>
|