peninsula123 commited on
Commit
5c90dd1
·
0 Parent(s):

docs: add OpenCortex MVP design

Browse files
docs/superpowers/specs/2026-06-09-open-cortex-mvp-design.md ADDED
@@ -0,0 +1,541 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OpenCortex MVP Design
2
+
3
+ ## 1. Product Definition
4
+
5
+ OpenCortex is a real-time observatory for local LLM inference. It combines a
6
+ chat experience with a visual representation of the runtime that produces each
7
+ response.
8
+
9
+ The product must communicate within ten seconds that:
10
+
11
+ 1. The model is actively processing and generating.
12
+ 2. Memory, context, speed, and engine health are distinct runtime concerns.
13
+ 3. These runtime states affect the user's conversation experience.
14
+ 4. The evidence comes from the inference engine, not from decorative UI.
15
+
16
+ The product is positioned as:
17
+
18
+ - Chrome DevTools for LLM inference.
19
+ - A restrained sci-fi cockpit for a local AI engine.
20
+ - A transparent artificial cognitive machine.
21
+
22
+ It must not resemble a generic metrics dashboard, Grafana, or a default Gradio
23
+ application.
24
+
25
+ ## 2. MVP Scope
26
+
27
+ ### Included
28
+
29
+ - Streaming bilingual chat input and output.
30
+ - English and Chinese UI switching.
31
+ - A resizable conversation panel.
32
+ - Automatic conversation drawer collapse below a width threshold.
33
+ - A runtime observatory with:
34
+ - Cortex Core.
35
+ - Working Memory.
36
+ - Context Window.
37
+ - Token Stream.
38
+ - Engine State.
39
+ - Runtime experiments:
40
+ - Normal chat.
41
+ - Long context stress.
42
+ - Memory pressure.
43
+ - Slow decode.
44
+ - Context collapse.
45
+ - A development-only runtime simulator.
46
+ - A real llama.cpp backend with streamed inference and telemetry.
47
+ - Local and remote llama.cpp deployment modes.
48
+ - Hugging Face Gradio Space packaging.
49
+ - Modal-compatible remote deployment without coupling the UI to Modal.
50
+
51
+ ### Excluded
52
+
53
+ - Multi-user production scheduling.
54
+ - Authentication and persistent user accounts.
55
+ - Historical dashboards and trace search.
56
+ - Runtime replay.
57
+ - A Prometheus or Grafana deployment.
58
+ - vLLM integration in v0.1.
59
+ - WebSocket infrastructure beyond what Gradio and streaming HTTP require.
60
+ - Claims about neural or biological equivalence.
61
+
62
+ ## 3. Design Principles
63
+
64
+ ### 3.1 Cognitive Naming, Engineering Structure
65
+
66
+ The interface uses human-readable cognitive concepts while rendering them as
67
+ engineering components:
68
+
69
+ | Product concept | Engineering form | Runtime evidence |
70
+ | --- | --- | --- |
71
+ | Cortex Core | Transparent processor/reactor core | Current phase and decode step |
72
+ | Working Memory | KV cell bank | KV/cache usage and cache events |
73
+ | Context Window | Sliding memory tape | Used and maximum context tokens |
74
+ | Token Stream | Decode pulse conduit | Tokens per second and token intervals |
75
+ | Engine State | Rhythm monitor | TTFT and engine health |
76
+
77
+ The interface must not depict literal human brain regions. That would imply
78
+ unsupported neuroscience mappings and weaken technical credibility.
79
+
80
+ ### 3.2 Semantic State With Metric Evidence
81
+
82
+ Every organ shows:
83
+
84
+ 1. A semantic state, such as `Memory holding`.
85
+ 2. One primary metric, such as `63%`.
86
+ 3. A unique visual structure that changes with the metric.
87
+
88
+ Raw evidence remains available in a compact telemetry strip. It does not compete
89
+ with the main state visualization.
90
+
91
+ ### 3.3 Color Semantics
92
+
93
+ - Cyan: active computation, data flow, and healthy runtime activity.
94
+ - Orange: recoverable pressure or degraded performance.
95
+ - Red/magenta: irreversible user-visible loss, such as forgotten context.
96
+ - Slate: inactive structure, labels, boundaries, and secondary information.
97
+
98
+ Only the affected organ, connection, and corresponding part of the Cortex Core
99
+ receive warning color. The whole screen must not change color for a local fault.
100
+
101
+ ### 3.4 Information Hierarchy
102
+
103
+ The interface uses three levels:
104
+
105
+ 1. Semantic state.
106
+ 2. Primary metric.
107
+ 3. Compact raw engine evidence.
108
+
109
+ The MVP removes repeated subtitles, engineering aliases, metric explanations,
110
+ turn counters, decorative status labels, and duplicated telemetry.
111
+
112
+ ## 4. Layout
113
+
114
+ The application has a compact product header and a two-panel workspace.
115
+
116
+ ### Header
117
+
118
+ - OpenCortex identity.
119
+ - Backend connection status.
120
+ - English/Chinese switch.
121
+
122
+ ### Conversation Panel
123
+
124
+ - Current experiment label.
125
+ - Conversation history.
126
+ - Active context boundary when older messages leave model-visible context.
127
+ - Streaming assistant message.
128
+ - Message composer.
129
+
130
+ ### Divider
131
+
132
+ - A vertical divider supports horizontal panel resizing.
133
+ - The conversation width is constrained to a practical maximum.
134
+ - Below a collapse threshold, the conversation becomes a hidden drawer.
135
+ - A visible control restores the drawer.
136
+ - Double-clicking the divider toggles the drawer.
137
+
138
+ ### Runtime Observatory
139
+
140
+ - Compact model identity, runtime phase, and experiment controls.
141
+ - Cortex Core in the center.
142
+ - Four organs connected to the core.
143
+ - A compact engine evidence strip.
144
+
145
+ The V6 visual prototype is the design reference. Prototype artifacts remain
146
+ outside version control under `.superpowers/`.
147
+
148
+ ## 5. Runtime State Model
149
+
150
+ The frontend receives one normalized state independent of the inference
151
+ backend.
152
+
153
+ ```python
154
+ from dataclasses import dataclass
155
+ from enum import StrEnum
156
+
157
+
158
+ class RuntimePhase(StrEnum):
159
+ IDLE = "idle"
160
+ PREFILL = "prefill"
161
+ DECODE = "decode"
162
+ RECOVERY = "recovery"
163
+ ERROR = "error"
164
+
165
+
166
+ class Severity(StrEnum):
167
+ QUIET = "quiet"
168
+ HEALTHY = "healthy"
169
+ BUSY = "busy"
170
+ STRAINED = "strained"
171
+ DEGRADED = "degraded"
172
+
173
+
174
+ @dataclass(frozen=True)
175
+ class WorkingMemoryState:
176
+ severity: Severity
177
+ label: str
178
+ usage_percent: float
179
+ cache_evictions: int | None
180
+
181
+
182
+ @dataclass(frozen=True)
183
+ class ContextWindowState:
184
+ severity: Severity
185
+ label: str
186
+ used_tokens: int
187
+ max_tokens: int
188
+ forgotten_message_ids: tuple[str, ...]
189
+
190
+
191
+ @dataclass(frozen=True)
192
+ class TokenStreamState:
193
+ severity: Severity
194
+ label: str
195
+ tokens_per_second: float
196
+ last_token_interval_ms: float | None
197
+
198
+
199
+ @dataclass(frozen=True)
200
+ class EngineState:
201
+ severity: Severity
202
+ label: str
203
+ ttft_ms: float | None
204
+ prompt_tokens_per_second: float | None
205
+
206
+
207
+ @dataclass(frozen=True)
208
+ class RuntimeState:
209
+ sequence: int
210
+ phase: RuntimePhase
211
+ model_name: str
212
+ working_memory: WorkingMemoryState
213
+ context_window: ContextWindowState
214
+ token_stream: TokenStreamState
215
+ engine: EngineState
216
+ ```
217
+
218
+ `sequence` is monotonically increasing per request so the browser can ignore
219
+ late events.
220
+
221
+ ## 6. Runtime Event Protocol
222
+
223
+ State snapshots are accompanied by streamed events:
224
+
225
+ ```python
226
+ @dataclass(frozen=True)
227
+ class RuntimeEvent:
228
+ request_id: str
229
+ sequence: int
230
+ kind: str
231
+ state: RuntimeState
232
+ text_delta: str = ""
233
+ forgotten_message_ids: tuple[str, ...] = ()
234
+ ```
235
+
236
+ Supported `kind` values:
237
+
238
+ - `request_started`
239
+ - `prefill_progress`
240
+ - `first_token`
241
+ - `token`
242
+ - `context_forgotten`
243
+ - `request_completed`
244
+ - `request_failed`
245
+
246
+ The Python layer serializes these objects to JSON-compatible dictionaries.
247
+ Gradio yields chat and runtime updates from the same generator so UI state and
248
+ text stay causally aligned.
249
+
250
+ ## 7. State Derivation
251
+
252
+ Semantic states are deterministic mappings from measured values. Thresholds are
253
+ configuration, not hard-coded UI behavior.
254
+
255
+ Example defaults:
256
+
257
+ | Signal | Healthy | Busy | Strained | Degraded |
258
+ | --- | --- | --- | --- | --- |
259
+ | KV/cache usage | `< 60%` | `60-79%` | `80-94%` | `>= 95%` |
260
+ | Context usage | `< 60%` | `60-79%` | `80-94%` | forgotten context event |
261
+ | Decode speed | benchmark-dependent | below baseline | `< 50%` baseline | stalled |
262
+ | TTFT | benchmark-dependent | above baseline | `> 2x` baseline | timeout/error |
263
+
264
+ Speed and latency thresholds are relative to a benchmark profile recorded for
265
+ the active model and deployment. The profile is generated by the project
266
+ benchmark command and loaded at application startup. Fixed universal thresholds
267
+ would be misleading across CPU, GPU, local, and remote deployments.
268
+
269
+ ## 8. Experiment Semantics
270
+
271
+ Experiments identify causes. Severity identifies impact. They are separate.
272
+
273
+ ### Normal Chat
274
+
275
+ - Standard prompt and generation.
276
+ - Stable core pulse.
277
+ - All organs remain healthy unless real metrics indicate otherwise.
278
+
279
+ ### Long Context Stress
280
+
281
+ - Submit a deliberately long prompt/history.
282
+ - Context tape fills toward the limit.
283
+ - Prefill duration and TTFT increase.
284
+ - Decode can remain healthy after prefill.
285
+ - Early messages visually fade but remain active until the engine reports they
286
+ are no longer in context.
287
+
288
+ ### Memory Pressure
289
+
290
+ - Create controlled slot/cache pressure with background requests that retain
291
+ long contexts on the dedicated demo backend.
292
+ - Read the resulting cache and slot behavior from llama.cpp telemetry.
293
+ - KV cells visibly relocate, darken, and refill.
294
+ - The memory-to-core connection becomes irregular.
295
+ - Context and token flow remain visually stable unless their measured values
296
+ also degrade.
297
+ - The assistant expresses uncertainty about early details instead of narrating
298
+ the interface.
299
+
300
+ ### Slow Decode
301
+
302
+ - Create controlled decode contention with parallel short-context generation
303
+ requests on the dedicated demo backend.
304
+ - Use the measured foreground token arrival cadence as the displayed speed.
305
+ - Token pulses follow a stop-burst-stop rhythm.
306
+ - Text streaming uses the actual token arrival timing.
307
+ - Working memory and context remain visually healthy.
308
+
309
+ ### Context Collapse
310
+
311
+ - Fill the active context until the oldest conversation content is no longer
312
+ included in the model prompt.
313
+ - Show an `Active Context Boundary` in the chat history.
314
+ - Messages outside the active context remain in the UI but become visually
315
+ marked as forgotten.
316
+ - The memory tape releases its oldest segments and returns to a stable usage
317
+ level.
318
+ - The assistant demonstrates lost long-range recall.
319
+
320
+ The experiment controller may prepare prompts and backend configuration, but it
321
+ must not invent final runtime metrics.
322
+
323
+ The controlled load generator is part of the demo backend, not a production
324
+ scheduler. Experiments that cannot be isolated safely on the active deployment
325
+ are disabled.
326
+
327
+ ## 9. Data Truthfulness
328
+
329
+ There are two explicit modes.
330
+
331
+ ### Simulator Mode
332
+
333
+ - Used for frontend development, tests, screenshots, and offline demos.
334
+ - Clearly labeled as simulated.
335
+ - Produces deterministic fixture events.
336
+
337
+ ### Live Mode
338
+
339
+ - Used for the submitted interactive inference demo.
340
+ - Displays only values measured by llama.cpp or directly measured at the
341
+ OpenCortex request boundary.
342
+ - Unsupported metrics are omitted, not estimated.
343
+ - Network latency and backend inference latency remain distinguishable for a
344
+ remote backend.
345
+
346
+ ## 10. Architecture
347
+
348
+ ```text
349
+ Gradio Blocks
350
+ |
351
+ +-- Custom HTML/CSS shell based on V6
352
+ +-- Small browser controller
353
+ | +-- runtime animations
354
+ | +-- resizable split view
355
+ | +-- drawer behavior
356
+ | +-- localization
357
+ |
358
+ +-- ChatController
359
+ |
360
+ +-- RuntimeStateEngine
361
+ |
362
+ +-- InferenceBackend
363
+ +-- SimulatedBackend
364
+ +-- LlamaCppBackend
365
+ +-- local llama-server
366
+ +-- remote llama-server
367
+ +-- future VllmBackend
368
+ ```
369
+
370
+ ### Frontend Strategy
371
+
372
+ Use Gradio Blocks for event wiring, queuing, session state, and Hugging Face
373
+ Space compatibility. Render the product surface with custom HTML and CSS. Use a
374
+ small JavaScript controller for interactions Gradio does not model well.
375
+
376
+ The browser controller must be framework-free for the MVP. Adding React would
377
+ create a second application lifecycle and unnecessary build complexity.
378
+
379
+ ### Backend Interface
380
+
381
+ ```python
382
+ class InferenceBackend(Protocol):
383
+ def stream_chat(
384
+ self,
385
+ messages: list[ChatMessage],
386
+ config: GenerationConfig,
387
+ experiment: ExperimentScenario,
388
+ ) -> Iterator[RuntimeEvent]:
389
+ ...
390
+ ```
391
+
392
+ The UI and state engine depend only on this protocol.
393
+
394
+ ### llama.cpp Integration
395
+
396
+ Use `llama-server` rather than embedding a Python binding. This provides:
397
+
398
+ - OpenAI-compatible streaming chat.
399
+ - Prompt progress and timing fields.
400
+ - `/metrics` when enabled.
401
+ - `/slots` for slot and cache inspection.
402
+ - Local and remote operation through the same HTTP client.
403
+
404
+ The integration layer correlates a chat request with snapshots taken before,
405
+ during, and after generation. Request-boundary timings are captured with a
406
+ monotonic clock.
407
+
408
+ ## 11. Model and Context Selection
409
+
410
+ The initial candidate is a GGUF instruction model with at most 4B parameters,
411
+ with Llama 3.2 3B Instruct as the first benchmark target.
412
+
413
+ The final model and default context are chosen by benchmark, not assumption.
414
+ Benchmark configurations include 2K, 4K, and 8K context where supported.
415
+
416
+ Selection criteria:
417
+
418
+ - Time to first token.
419
+ - Decode tokens per second.
420
+ - Memory/cache headroom.
421
+ - Bilingual response quality.
422
+ - Ability to demonstrate context behavior within a short session.
423
+ - Hugging Face licensing and redistribution requirements.
424
+
425
+ ## 12. Deployment
426
+
427
+ ### Mode A: Self-Contained Hugging Face Space
428
+
429
+ - Gradio and llama.cpp run in the Space.
430
+ - Preferred when CPU or available Space hardware gives an acceptable
431
+ experience.
432
+ - Strongest fit for a self-contained demo.
433
+
434
+ ### Mode B: Hugging Face Space With Remote llama.cpp
435
+
436
+ - The Space hosts Gradio.
437
+ - Modal or another host runs llama.cpp.
438
+ - Selected by environment configuration.
439
+ - The UI separately reports frontend-to-backend network latency when relevant.
440
+
441
+ The repository supports both modes. The final submission mode is selected after
442
+ benchmarking rather than embedded into the product architecture.
443
+
444
+ ZeroGPU is not the primary llama.cpp deployment assumption because its
445
+ request-scoped GPU lifecycle is designed around supported PyTorch workloads.
446
+
447
+ ## 13. Error Handling
448
+
449
+ - Backend unavailable: keep chat history, mark runtime disconnected, and show a
450
+ retry action.
451
+ - Stream interrupted: retain partial output and mark the request incomplete.
452
+ - Metrics endpoint unavailable: continue chat, hide unavailable evidence, and
453
+ never substitute estimates.
454
+ - Context exceeds configured input: apply the same deterministic prompt
455
+ truncation policy used by the backend and emit `context_forgotten`.
456
+ - Stale browser event: discard by `request_id` and `sequence`.
457
+ - Experiment unsupported by active backend: disable it with a concise reason.
458
+
459
+ ## 14. Testing
460
+
461
+ ### Unit Tests
462
+
463
+ - Semantic threshold mapping.
464
+ - Context boundary and forgotten message selection.
465
+ - Event ordering and stale event rejection.
466
+ - Local/remote backend URL configuration.
467
+ - llama.cpp response and metrics parsing.
468
+
469
+ ### Contract Tests
470
+
471
+ - Fixture streams for all runtime event types.
472
+ - SimulatedBackend and LlamaCppBackend conform to the same event protocol.
473
+ - Missing metrics remain `None` and do not become estimated values.
474
+
475
+ ### UI Tests
476
+
477
+ - Each experiment activates only the intended organs and connection.
478
+ - Slow decode changes text timing.
479
+ - Context collapse displays the active context boundary.
480
+ - Dragging the divider resizes the panels.
481
+ - Dragging below the threshold collapses the conversation drawer.
482
+ - English/Chinese switching updates semantic labels.
483
+
484
+ ### Integration Tests
485
+
486
+ - A small llama.cpp test model produces a complete prefill/decode event stream.
487
+ - Chat text and runtime state remain ordered under streaming.
488
+ - Remote mode reports network and backend timing separately.
489
+
490
+ ## 15. Repository Shape
491
+
492
+ ```text
493
+ open-cortex/
494
+ app.py
495
+ pyproject.toml
496
+ README.md
497
+ src/open_cortex/
498
+ backends/
499
+ base.py
500
+ llama_cpp.py
501
+ simulated.py
502
+ runtime/
503
+ models.py
504
+ state_engine.py
505
+ thresholds.py
506
+ ui/
507
+ app.py
508
+ localization.py
509
+ assets/
510
+ open_cortex.css
511
+ open_cortex.js
512
+ tests/
513
+ backends/
514
+ runtime/
515
+ ui/
516
+ deploy/
517
+ modal/
518
+ huggingface/
519
+ ```
520
+
521
+ Implementation replaces the current scaffold `main.py` with `app.py` as the
522
+ Space and local development entry point.
523
+
524
+ ## 16. Acceptance Criteria
525
+
526
+ The MVP is accepted when:
527
+
528
+ 1. A user can chat with a model and see streamed output.
529
+ 2. Runtime state changes during prefill and decode.
530
+ 3. Working Memory, Context Window, Token Stream, and Engine State are visually
531
+ distinct without relying on labels alone.
532
+ 4. The five experiments are distinguishable by affected organ, timing, and
533
+ assistant behavior.
534
+ 5. Context collapse leaves history visible while marking forgotten messages
535
+ outside the active context boundary.
536
+ 6. The conversation panel can be resized, collapsed by threshold, and restored.
537
+ 7. Live mode displays only real measured evidence.
538
+ 8. The same UI runs against local and remote llama.cpp through configuration.
539
+ 9. The application deploys as a Gradio Hugging Face Space.
540
+ 10. The first screen reads as an inference observatory rather than a chatbot or
541
+ generic monitoring dashboard.