create-walle 0.9.31 → 0.9.32
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/package.json +1 -1
- package/template/claude-task-manager/api-prompts.js +406 -1
- package/template/claude-task-manager/api-reviews.js +104 -6
- package/template/claude-task-manager/approval-agent.js +293 -27
- package/template/claude-task-manager/db.js +77 -13
- package/template/claude-task-manager/docs/codex-app-server-approvals.md +35 -1
- package/template/claude-task-manager/docs/postgres-concurrency-dgx-spark.html +407 -0
- package/template/claude-task-manager/docs/prompt-manager-redesign-proposal.html +24 -23
- package/template/claude-task-manager/docs/unified-auto-approver-proposal.html +520 -0
- package/template/claude-task-manager/git-utils.js +164 -26
- package/template/claude-task-manager/lib/agent-capabilities.js +26 -5
- package/template/claude-task-manager/lib/agent-cli-cache.js +1 -1
- package/template/claude-task-manager/lib/agent-presets.js +12 -0
- package/template/claude-task-manager/lib/agent-version-service.js +650 -0
- package/template/claude-task-manager/lib/approval-drift.js +57 -0
- package/template/claude-task-manager/lib/approval-hook.js +13 -0
- package/template/claude-task-manager/lib/auth-rules.js +6 -0
- package/template/claude-task-manager/lib/broadcast-payload-memo.js +109 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +89 -8
- package/template/claude-task-manager/lib/document-review.js +75 -1
- package/template/claude-task-manager/lib/escalation-review.js +33 -3
- package/template/claude-task-manager/lib/headless-term-service.js +42 -8
- package/template/claude-task-manager/lib/mcp-risk.js +128 -0
- package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +51 -2
- package/template/claude-task-manager/lib/native-agent-model-args.js +31 -0
- package/template/claude-task-manager/lib/opencode-conversation-store.js +269 -0
- package/template/claude-task-manager/lib/permission-match.js +77 -5
- package/template/claude-task-manager/lib/read-pool-client.js +15 -6
- package/template/claude-task-manager/lib/restore-backoff.js +82 -0
- package/template/claude-task-manager/lib/runtime-registry.js +1 -0
- package/template/claude-task-manager/lib/scheduled-wake.js +42 -0
- package/template/claude-task-manager/lib/session-capture.js +33 -6
- package/template/claude-task-manager/lib/session-history.js +56 -2
- package/template/claude-task-manager/lib/session-jobs.js +19 -0
- package/template/claude-task-manager/lib/session-restore.js +5 -4
- package/template/claude-task-manager/lib/session-standup.js +2 -0
- package/template/claude-task-manager/lib/session-stream.js +9 -0
- package/template/claude-task-manager/lib/state-sync/cell-diff.js +31 -4
- package/template/claude-task-manager/lib/state-sync/restore-frame-hold.js +39 -0
- package/template/claude-task-manager/lib/walle-ctm-history.js +103 -36
- package/template/claude-task-manager/lib/walle-session-model-catalog.js +7 -1
- package/template/claude-task-manager/lib/walle-token-chip.js +65 -0
- package/template/claude-task-manager/package.json +1 -1
- package/template/claude-task-manager/providers/codex-mcp-extract.js +33 -0
- package/template/claude-task-manager/providers/codex-mcp.js +23 -20
- package/template/claude-task-manager/providers/codex.js +65 -1
- package/template/claude-task-manager/public/css/prompts.css +345 -0
- package/template/claude-task-manager/public/css/reviews.css +16 -40
- package/template/claude-task-manager/public/css/walle-session.css +90 -26
- package/template/claude-task-manager/public/index.html +1251 -299
- package/template/claude-task-manager/public/js/document-review-links.js +215 -9
- package/template/claude-task-manager/public/js/message-renderer.js +19 -0
- package/template/claude-task-manager/public/js/mobile-review-core.js +54 -0
- package/template/claude-task-manager/public/js/prompt-diff.js +55 -0
- package/template/claude-task-manager/public/js/prompt-editor-chrome.js +108 -0
- package/template/claude-task-manager/public/js/prompt-editor-modes.js +87 -0
- package/template/claude-task-manager/public/js/prompt-organize.js +179 -0
- package/template/claude-task-manager/public/js/prompt-reuse.js +77 -0
- package/template/claude-task-manager/public/js/prompts.js +683 -215
- package/template/claude-task-manager/public/js/reviews.js +28 -54
- package/template/claude-task-manager/public/js/session-search-utils.js +55 -0
- package/template/claude-task-manager/public/js/state-sync-client.js +40 -1
- package/template/claude-task-manager/public/js/stream-view.js +6 -0
- package/template/claude-task-manager/public/js/walle-session.js +183 -32
- package/template/claude-task-manager/public/js/walle.js +21 -9
- package/template/claude-task-manager/public/m/app.css +117 -0
- package/template/claude-task-manager/public/m/app.js +309 -3
- package/template/claude-task-manager/public/m/index.html +56 -1
- package/template/claude-task-manager/server.js +573 -299
- package/template/claude-task-manager/workers/db-owner-worker.js +8 -0
- package/template/claude-task-manager/workers/read-pool-worker.js +4 -0
- package/template/claude-task-manager/workers/state-detectors/claude-code.js +10 -1
- package/template/docs/proposals/2026-06-23-local-model-right-path.html +340 -0
- package/template/docs/proposals/2026-06-24-qlora-done-right.md +255 -0
- package/template/package.json +1 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +27 -4
- package/template/wall-e/brain.js +50 -5
- package/template/wall-e/chat/force-compact.js +73 -0
- package/template/wall-e/chat.js +54 -19
- package/template/wall-e/coding/action-memory-policy.js +120 -1
- package/template/wall-e/coding/compaction-service.js +10 -3
- package/template/wall-e/coding/model-router.js +116 -0
- package/template/wall-e/coding-orchestrator.js +303 -11
- package/template/wall-e/coding-prompts.js +1 -1
- package/template/wall-e/docs/skill-self-heal-design.html +429 -0
- package/template/wall-e/llm/client.js +53 -3
- package/template/wall-e/llm/default-fallback.js +59 -5
- package/template/wall-e/llm/mlx-worker.js +0 -0
- package/template/wall-e/llm/mlx.js +46 -12
- package/template/wall-e/llm/provider-error.js +2 -2
- package/template/wall-e/llm/provider-health-state.js +6 -2
- package/template/wall-e/llm/tool-call-validator.js +156 -0
- package/template/wall-e/skills/skill-dispatch-decision.js +82 -2
- package/template/wall-e/skills/skill-planner.js +72 -5
- package/template/wall-e/tools/command-registry.js +34 -0
- package/template/wall-e/training/gemma-e4b-qlora.js +197 -1
- package/template/wall-e/training/mlx_lora_launch.py +196 -0
- package/template/wall-e/training/training-coexistence.sh +87 -0
- package/template/wall-e/training/training-mem-guard.sh +76 -0
|
@@ -0,0 +1,407 @@
|
|
|
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>CTM + Wall-E · Postgres, Concurrency & the Supercomputer-as-a-Service Question</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root{
|
|
9
|
+
--bg:#0b0e14; --panel:#11161f; --panel2:#161d28; --ink:#e6edf3; --dim:#9aa7b8;
|
|
10
|
+
--line:#212a37; --accent:#5ec8ff; --accent2:#7ee787; --warn:#ffb86b; --bad:#ff7b72;
|
|
11
|
+
--grace:#76e0c2; --pg:#7aa2ff; --gpu:#9d7bff; --mono:"SF Mono",ui-monospace,"JetBrains Mono",Menlo,Consolas,monospace;
|
|
12
|
+
}
|
|
13
|
+
*{box-sizing:border-box}
|
|
14
|
+
html{scroll-behavior:smooth}
|
|
15
|
+
body{
|
|
16
|
+
margin:0;background:radial-gradient(1200px 700px at 80% -10%,#16202e 0%,var(--bg) 55%);
|
|
17
|
+
color:var(--ink);font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,sans-serif;
|
|
18
|
+
-webkit-font-smoothing:antialiased;padding-bottom:6rem;
|
|
19
|
+
}
|
|
20
|
+
.wrap{max-width:1040px;margin:0 auto;padding:0 24px}
|
|
21
|
+
header.hero{padding:64px 24px 40px;max-width:1040px;margin:0 auto}
|
|
22
|
+
.kicker{font:600 12px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accent);margin-bottom:18px}
|
|
23
|
+
h1{font-size:40px;line-height:1.12;margin:0 0 16px;letter-spacing:-.02em;font-weight:740}
|
|
24
|
+
h1 .g{background:linear-gradient(100deg,var(--grace),var(--pg) 55%,var(--gpu));-webkit-background-clip:text;background-clip:text;color:transparent}
|
|
25
|
+
.sub{font-size:18px;color:var(--dim);max-width:74ch;margin:0}
|
|
26
|
+
.meta{margin-top:22px;font:500 13px/1.5 var(--mono);color:var(--dim)}
|
|
27
|
+
.meta b{color:var(--ink);font-weight:600}
|
|
28
|
+
|
|
29
|
+
h2{font-size:25px;letter-spacing:-.01em;margin:56px 0 8px;font-weight:700;scroll-margin-top:20px}
|
|
30
|
+
h2 .n{font:700 14px/1 var(--mono);color:var(--accent);margin-right:12px;vertical-align:2px}
|
|
31
|
+
h3{font-size:18px;margin:30px 0 8px;font-weight:660}
|
|
32
|
+
p{margin:12px 0}
|
|
33
|
+
a{color:var(--accent);text-decoration:none;border-bottom:1px solid #2c4a5e}
|
|
34
|
+
a:hover{border-color:var(--accent)}
|
|
35
|
+
.lead{color:var(--dim);font-size:16.5px;margin-top:4px}
|
|
36
|
+
code{font:13.5px/1.5 var(--mono);background:#0d141d;border:1px solid var(--line);border-radius:5px;padding:1px 6px;color:#cfe6ff}
|
|
37
|
+
strong{color:#fff;font-weight:660}
|
|
38
|
+
em{color:var(--ink);font-style:italic}
|
|
39
|
+
|
|
40
|
+
.panel{background:linear-gradient(180deg,var(--panel),#0e131b);border:1px solid var(--line);border-radius:14px;padding:22px 24px;margin:22px 0}
|
|
41
|
+
.tldr{border-left:3px solid var(--accent)}
|
|
42
|
+
.tldr h2{margin-top:0}
|
|
43
|
+
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
|
|
44
|
+
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
|
|
45
|
+
@media(max-width:780px){.grid2,.grid3{grid-template-columns:1fr}}
|
|
46
|
+
.card{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
|
|
47
|
+
.card h4{margin:0 0 8px;font-size:15px;font-weight:660;display:flex;align-items:center;gap:8px}
|
|
48
|
+
.card p{margin:6px 0;font-size:14.5px;color:var(--dim)}
|
|
49
|
+
.pill{display:inline-block;font:600 11px/1 var(--mono);padding:5px 9px;border-radius:999px;border:1px solid var(--line);color:var(--dim);background:#0d141d}
|
|
50
|
+
.dot{width:9px;height:9px;border-radius:50%;display:inline-block;flex:none}
|
|
51
|
+
|
|
52
|
+
table{width:100%;border-collapse:collapse;margin:18px 0;font-size:14px}
|
|
53
|
+
th,td{text-align:left;padding:11px 13px;border-bottom:1px solid var(--line);vertical-align:top}
|
|
54
|
+
th{font:600 12px/1 var(--mono);letter-spacing:.05em;text-transform:uppercase;color:var(--dim)}
|
|
55
|
+
tbody tr:hover{background:#0f1620}
|
|
56
|
+
td code{font-size:12.5px}
|
|
57
|
+
.yes{color:var(--accent2)} .no{color:var(--bad)} .meh{color:var(--warn)}
|
|
58
|
+
|
|
59
|
+
.callout{border:1px solid var(--line);border-radius:12px;padding:14px 18px;margin:18px 0;background:#0e1019}
|
|
60
|
+
.callout.warn{border-color:#5a4326;background:#1a1408}
|
|
61
|
+
.callout.good{border-color:#26503a;background:#0a1710}
|
|
62
|
+
.callout .h{font:600 12px/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;margin-bottom:6px}
|
|
63
|
+
.callout.warn .h{color:var(--warn)} .callout.good .h{color:var(--accent2)}
|
|
64
|
+
.callout p{margin:4px 0;font-size:14.5px}
|
|
65
|
+
|
|
66
|
+
figure{margin:24px 0}
|
|
67
|
+
figcaption{font:500 12.5px/1.5 var(--mono);color:var(--dim);margin-top:10px;text-align:center}
|
|
68
|
+
svg{width:100%;height:auto;display:block}
|
|
69
|
+
.svgwrap{background:#0a0f17;border:1px solid var(--line);border-radius:14px;padding:18px}
|
|
70
|
+
|
|
71
|
+
ul.clean{list-style:none;padding:0;margin:12px 0}
|
|
72
|
+
ul.clean li{padding:7px 0 7px 26px;position:relative;color:var(--dim)}
|
|
73
|
+
ul.clean li::before{content:"";position:absolute;left:4px;top:14px;width:7px;height:7px;border-radius:50%;background:var(--accent)}
|
|
74
|
+
ul.clean li b{color:var(--ink)}
|
|
75
|
+
|
|
76
|
+
.toc{font:500 14px/1.9 var(--mono)}
|
|
77
|
+
.toc a{border:0;color:var(--dim);display:block}
|
|
78
|
+
.toc a:hover{color:var(--accent)}
|
|
79
|
+
.toc .num{color:var(--accent);display:inline-block;width:30px}
|
|
80
|
+
|
|
81
|
+
.legend{display:flex;gap:20px;flex-wrap:wrap;margin-top:14px;font:500 12.5px/1 var(--mono);color:var(--dim)}
|
|
82
|
+
.legend span{display:flex;align-items:center;gap:7px}
|
|
83
|
+
|
|
84
|
+
footer{margin-top:60px;padding-top:24px;border-top:1px solid var(--line);color:var(--dim);font-size:13.5px}
|
|
85
|
+
.src{font-size:13px;line-height:1.9}
|
|
86
|
+
.tag{font:600 10.5px/1 var(--mono);padding:4px 7px;border-radius:5px;border:1px solid var(--line);color:var(--dim)}
|
|
87
|
+
.tag.now{color:var(--accent2);border-color:#26503a}
|
|
88
|
+
.tag.soon{color:var(--warn);border-color:#5a4326}
|
|
89
|
+
.tag.far{color:var(--gpu);border-color:#3a2e5a}
|
|
90
|
+
hr{border:0;border-top:1px solid var(--line);margin:40px 0}
|
|
91
|
+
.big{font-size:30px;font-weight:740;letter-spacing:-.01em}
|
|
92
|
+
.num-strip{display:flex;gap:14px;flex-wrap:wrap;margin:18px 0}
|
|
93
|
+
.stat{flex:1;min-width:150px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:16px}
|
|
94
|
+
.stat .v{font-size:24px;font-weight:740;color:#fff}
|
|
95
|
+
.stat .l{font:500 12px/1.4 var(--mono);color:var(--dim);margin-top:4px}
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
<body>
|
|
99
|
+
|
|
100
|
+
<header class="hero">
|
|
101
|
+
<div class="kicker">CTM + Wall-E · Architecture Discussion · 2026-06-28</div>
|
|
102
|
+
<h1>Postgres, real concurrency, and the<br><span class="g">supercomputer-as-a-service</span> question</h1>
|
|
103
|
+
<p class="sub">An extension of the approved SQLite → Postgres migration spec. It asks a sharper question: once the data layer is async and networked, <em>how much concurrency do we actually have</em> — and what changes if CTM + Wall-E run as a multi-tenant service on a single dedicated AI box like an NVIDIA DGX Spark?</p>
|
|
104
|
+
<div class="meta">
|
|
105
|
+
Companion to <b>~/.claude/plans/let-s-discuss-do-online-frolicking-pascal.md</b> (Phases 0–5)<br>
|
|
106
|
+
Status: <b>discussion / design exploration</b> — not a commitment. Phase 0 async seam already shipped on <b>feat/db-async-seam</b>.
|
|
107
|
+
</div>
|
|
108
|
+
</header>
|
|
109
|
+
|
|
110
|
+
<div class="wrap">
|
|
111
|
+
|
|
112
|
+
<div class="panel tldr">
|
|
113
|
+
<h2 style="border:0">TL;DR</h2>
|
|
114
|
+
<ul class="clean">
|
|
115
|
+
<li><b>The concurrency we have today is mostly <em>fake</em>.</b> One user, one machine — but dozens of background workers (harvest, backfill, import, embeddings, approval agent) all contending for a <em>single SQLite writer</em>. That contention <em>is</em> the freeze story.</li>
|
|
116
|
+
<li><b>Postgres doesn't make things faster — it removes the single-writer ceiling.</b> MVCC lets readers and writers run concurrently. The async seam (Phase 0) is what lets Node actually use that concurrency instead of blocking the event loop on it.</li>
|
|
117
|
+
<li><b>Real concurrency only appears when you go multi-device / multi-agent.</b> That's when SQLite's file-lock model genuinely breaks and a server engine becomes <em>required</em>, not just nicer.</li>
|
|
118
|
+
<li><b>The DGX Spark angle is real, and oddly well-matched.</b> One box co-locates Postgres + pgvector + GPU embedding/inference in 128 GB unified memory. EDB's GPU-accelerated Postgres vector extension <em>explicitly lists the GB10 chip</em> (the one inside Spark) as supported. It turns "hosted DB + cloud LLM calls" into "one local node does all of it."</li>
|
|
119
|
+
<li><b>Honest verdict:</b> a Spark is <em>overkill for one user</em> and <em>underkill for a real fleet</em>. It's compelling in exactly one scenario — a <b>private, always-on, multi-device + heavy-local-inference</b> deployment where you want everything on hardware you own. Worth designing toward; not worth buying for today's load.</li>
|
|
120
|
+
</ul>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div class="panel toc">
|
|
124
|
+
<a href="#concurrency"><span class="num">01</span> Where does "concurrency" actually come from?</a>
|
|
125
|
+
<a href="#wall"><span class="num">02</span> Why SQLite hits a wall under real concurrency</a>
|
|
126
|
+
<a href="#pg"><span class="num">03</span> The Postgres concurrency model (and why async is the unlock)</a>
|
|
127
|
+
<a href="#spark"><span class="num">04</span> The DGX Spark vision: one box, every subsystem</a>
|
|
128
|
+
<a href="#arch"><span class="num">05</span> Reference architecture</a>
|
|
129
|
+
<a href="#gpu"><span class="num">06</span> What the GPU actually buys you</a>
|
|
130
|
+
<a href="#sizing"><span class="num">07</span> Capacity & sizing — rough numbers</a>
|
|
131
|
+
<a href="#phasing"><span class="num">08</span> How this extends the Phase 0–5 plan</a>
|
|
132
|
+
<a href="#risks"><span class="num">09</span> Risks & honest caveats</a>
|
|
133
|
+
<a href="#verdict"><span class="num">10</span> Decision matrix: when is this worth it?</a>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- ───────────────────────────── 01 ───────────────────────────── -->
|
|
137
|
+
<h2 id="concurrency"><span class="n">01</span>Where does "concurrency" actually come from?</h2>
|
|
138
|
+
<p class="lead">Before designing for "more concurrency," be precise about which kind. CTM/Wall-E has three very different sources, and they live on opposite ends of the difficulty spectrum.</p>
|
|
139
|
+
|
|
140
|
+
<div class="grid3">
|
|
141
|
+
<div class="card">
|
|
142
|
+
<h4><span class="dot" style="background:var(--accent2)"></span>Intra-process <span class="tag now">today</span></h4>
|
|
143
|
+
<p>One Node process, many <em>async tasks</em>: SSE streams, PTY pumps, the queue engine, the approval agent, conversation catch-up polls. Concurrency is cooperative — anything synchronous blocks <em>all</em> of it.</p>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="card">
|
|
146
|
+
<h4><span class="dot" style="background:var(--accent2)"></span>Worker threads <span class="tag now">today</span></h4>
|
|
147
|
+
<p><code>read-pool-worker.js</code> + <code>db-owner-worker.js</code> already move heavy reads/writes off the main loop. But the writer is still <em>one serial lane</em> (<code>sqlite-owner-write-queue.js</code>) because SQLite allows one writer.</p>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="card">
|
|
150
|
+
<h4><span class="dot" style="background:var(--gpu)"></span>Multi-client <span class="tag far">future</span></h4>
|
|
151
|
+
<p>Phones, laptops, and <em>autonomous agents</em> all writing to the same brain at once. This is genuine parallelism — and the only kind that <em>forces</em> a server-class database.</p>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div class="callout">
|
|
156
|
+
<div class="h">The key reframe</div>
|
|
157
|
+
<p>Today's "concurrency" is really <strong>contention</strong>: ~a dozen background jobs queuing behind one SQLite writer and one event loop. Phase 0's async seam + Postgres MVCC turn that queue into real parallel execution. <em>Then</em> multi-device makes the parallelism genuinely external — which is the thing that justifies the whole migration beyond just killing freezes.</p>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<!-- ───────────────────────────── 02 ───────────────────────────── -->
|
|
161
|
+
<h2 id="wall"><span class="n">02</span>Why SQLite hits a wall under real concurrency</h2>
|
|
162
|
+
<p class="lead">SQLite is superb for a single embedded user. Its design choices become liabilities the moment concurrency stops being cooperative.</p>
|
|
163
|
+
|
|
164
|
+
<table>
|
|
165
|
+
<thead><tr><th>Dimension</th><th>SQLite (today)</th><th>Under real concurrency</th></tr></thead>
|
|
166
|
+
<tbody>
|
|
167
|
+
<tr><td><b>Writers</b></td><td>Exactly one at a time; WAL serializes</td><td class="no">N agents/devices → write-lock storms, retry backoff, the <code>sqlite-write-lock.js</code> machinery exists <em>precisely</em> to paper over this</td></tr>
|
|
168
|
+
<tr><td><b>Driver model</b></td><td><code>better-sqlite3</code> is <em>synchronous</em></td><td class="no">Any slow query blocks Node's single thread — a network DB call this way would freeze <em>worse</em></td></tr>
|
|
169
|
+
<tr><td><b>Reach</b></td><td>A file on local disk (worse on Dropbox/synced volumes)</td><td class="no">No second device can open the same file safely; no network protocol</td></tr>
|
|
170
|
+
<tr><td><b>Checkpoints</b></td><td>Manual WAL checkpoint, <code>wal_autocheckpoint=0</code></td><td class="meh">457 ms–3 s stalls observed; tuned around, never eliminated</td></tr>
|
|
171
|
+
<tr><td><b>Vector / FTS</b></td><td><code>sqlite-vec</code> int8 + FTS5, in-process</td><td class="meh">CPU-bound, single-host; can't be shared or GPU-accelerated</td></tr>
|
|
172
|
+
</tbody>
|
|
173
|
+
</table>
|
|
174
|
+
|
|
175
|
+
<p>None of this is a knock on SQLite — it's the right tool for an embedded single-writer app. The point is structural: <strong>the moment you want two writers or two devices, every one of these rows flips from "fine" to "fundamental blocker."</strong></p>
|
|
176
|
+
|
|
177
|
+
<!-- ───────────────────────────── 03 ───────────────────────────── -->
|
|
178
|
+
<h2 id="pg"><span class="n">03</span>The Postgres concurrency model (and why async is the unlock)</h2>
|
|
179
|
+
<p class="lead">Postgres replaces "one writer + a file lock" with MVCC: each transaction sees a consistent snapshot, readers never block writers, and writers only conflict on the same row. That is exactly the model multi-agent state needs.</p>
|
|
180
|
+
|
|
181
|
+
<div class="grid2">
|
|
182
|
+
<div class="card">
|
|
183
|
+
<h4><span class="dot" style="background:var(--pg)"></span>What Postgres gives</h4>
|
|
184
|
+
<ul class="clean" style="margin:0">
|
|
185
|
+
<li><b>MVCC</b> — concurrent readers + writers, no global lock</li>
|
|
186
|
+
<li><b>Connection pool</b> (pgbouncer) — many clients, bounded backend processes</li>
|
|
187
|
+
<li><b>Server-side compute</b> — heavy reads run in the engine, not in a Node worker shipping rows</li>
|
|
188
|
+
<li><b>Retire</b> <code>sqlite-write-lock.js</code>, <code>sqlite-owner-write-queue.js</code>, <code>db-owner-worker.js</code>, storage-policy guards</li>
|
|
189
|
+
</ul>
|
|
190
|
+
</div>
|
|
191
|
+
<div class="card">
|
|
192
|
+
<h4><span class="dot" style="background:var(--warn)"></span>What Postgres does <em>not</em> give for free</h4>
|
|
193
|
+
<ul class="clean" style="margin:0">
|
|
194
|
+
<li><b>Latency</b> — every in-process read becomes a round trip; needs caching + batching</li>
|
|
195
|
+
<li><b>Ops surface</b> — backups, vacuum tuning, connection security, uptime</li>
|
|
196
|
+
<li><b>The async refactor still has to happen</b> — a sync call to a network DB is the worst of both worlds</li>
|
|
197
|
+
</ul>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div class="callout good">
|
|
202
|
+
<div class="h">Why the async seam is the real hero</div>
|
|
203
|
+
<p>The Phase 0 seam (<code>db-async.js</code>, already shipped) is what makes Postgres' concurrency <em>usable</em> from Node. Without it, a networked query blocks the event loop and you've made freezes worse. With it, the same call site <code>await</code>s — Node stays responsive while N queries are in flight against the pool. <strong>One refactor serves both goals: kill freezes <em>and</em> enable concurrency.</strong></p>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<!-- ───────────────────────────── 04 ───────────────────────────── -->
|
|
207
|
+
<h2 id="spark"><span class="n">04</span>The DGX Spark vision: one box, every subsystem</h2>
|
|
208
|
+
<p class="lead">Today the stack is scattered: SQLite on local disk, Ollama on CPU, embeddings in-process, and the heavy reasoning (approval judge, coding agent, classifiers) farmed out to cloud Claude via Portkey. A DGX Spark collapses that into a single owned node.</p>
|
|
209
|
+
|
|
210
|
+
<div class="num-strip">
|
|
211
|
+
<div class="stat"><div class="v">128 GB</div><div class="l">unified LPDDR5X<br>CPU+GPU share it</div></div>
|
|
212
|
+
<div class="stat"><div class="v">1 PFLOP</div><div class="l">FP4 AI perf<br>Blackwell GPU</div></div>
|
|
213
|
+
<div class="stat"><div class="v">20 cores</div><div class="l">Arm: 10× X925<br>+ 10× A725</div></div>
|
|
214
|
+
<div class="stat"><div class="v">200 GbE</div><div class="l">ConnectX-7<br>link 2 units → 405B</div></div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<p>The unified-memory design is the interesting part for <em>us</em> specifically. Postgres' shared buffers, pgvector's HNSW index, and a local LLM's weights can all live in the same 128 GB pool with no PCIe copy between "CPU memory" and "GPU memory." For a workload that is equal parts <b>transactional state</b> (Postgres), <b>vector recall</b> (pgvector/cuVS), and <b>inference</b> (embeddings + local judge models), that's an unusually good fit.</p>
|
|
218
|
+
|
|
219
|
+
<div class="callout good">
|
|
220
|
+
<div class="h">The concrete tie-in that makes this non-hypothetical</div>
|
|
221
|
+
<p>EDB's GPU-accelerated Postgres vector extension (<b>PGPU</b>, open-sourced Dec 2025) accelerates <code>VectorChord</code> index builds on NVIDIA GPUs — and its supported-architecture list <strong>explicitly includes GB10</strong>, the exact superchip inside a DGX Spark. So "run Postgres with GPU-accelerated vector indexing on a Spark" is a supported configuration today, not a research project.</p>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<h3>What moves onto the box</h3>
|
|
225
|
+
<table>
|
|
226
|
+
<thead><tr><th>Subsystem</th><th>Today</th><th>On a Spark</th></tr></thead>
|
|
227
|
+
<tbody>
|
|
228
|
+
<tr><td>Transactional state</td><td>SQLite file (local/Dropbox)</td><td>Postgres, served to all devices on the LAN/VPN</td></tr>
|
|
229
|
+
<tr><td>Vector recall (Wall-E brain)</td><td><code>sqlite-vec</code> int8, CPU, in-proc</td><td><code>pgvector</code>/VectorChord, GPU-built index (cuVS CAGRA/IVF-PQ)</td></tr>
|
|
230
|
+
<tr><td>Embeddings</td><td>CPU / small model</td><td>GPU batch embedding, much higher throughput</td></tr>
|
|
231
|
+
<tr><td>Local LLM (gemma/classifiers)</td><td>Ollama on CPU, ~87 tok/s</td><td>Blackwell GPU — large local models at interactive speed</td></tr>
|
|
232
|
+
<tr><td>Heavy reasoning (judge, coding agent)</td><td>Cloud Claude via Portkey</td><td>Hybrid: local for cheap/private turns, cloud for frontier — your call per route</td></tr>
|
|
233
|
+
</tbody>
|
|
234
|
+
</table>
|
|
235
|
+
|
|
236
|
+
<!-- ───────────────────────────── 05 ───────────────────────────── -->
|
|
237
|
+
<h2 id="arch"><span class="n">05</span>Reference architecture</h2>
|
|
238
|
+
<p class="lead">The same async data-access seam fronts everything. Devices and agents are just more clients of one pool; the GPU subsystems sit beside Postgres in shared memory.</p>
|
|
239
|
+
|
|
240
|
+
<figure>
|
|
241
|
+
<div class="svgwrap">
|
|
242
|
+
<svg viewBox="0 0 920 470" role="img" aria-label="DGX Spark co-located architecture diagram">
|
|
243
|
+
<defs>
|
|
244
|
+
<marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">
|
|
245
|
+
<path d="M0,0 L9,4.5 L0,9 z" fill="#5a6b80"/>
|
|
246
|
+
</marker>
|
|
247
|
+
<linearGradient id="boxg" x1="0" y1="0" x2="0" y2="1">
|
|
248
|
+
<stop offset="0" stop-color="#141c28"/><stop offset="1" stop-color="#0e131b"/>
|
|
249
|
+
</linearGradient>
|
|
250
|
+
</defs>
|
|
251
|
+
<rect x="0" y="0" width="920" height="470" fill="none"/>
|
|
252
|
+
|
|
253
|
+
<!-- clients -->
|
|
254
|
+
<text x="40" y="34" fill="#9aa7b8" font-family="monospace" font-size="12" font-weight="600">CLIENTS</text>
|
|
255
|
+
<g font-family="-apple-system,sans-serif" font-size="13" fill="#e6edf3">
|
|
256
|
+
<rect x="40" y="46" width="150" height="44" rx="9" fill="url(#boxg)" stroke="#212a37"/><text x="115" y="73" text-anchor="middle">📱 Phone (PWA)</text>
|
|
257
|
+
<rect x="40" y="104" width="150" height="44" rx="9" fill="url(#boxg)" stroke="#212a37"/><text x="115" y="131" text-anchor="middle">💻 Laptop browser</text>
|
|
258
|
+
<rect x="40" y="162" width="150" height="44" rx="9" fill="url(#boxg)" stroke="#212a37"/><text x="115" y="189" text-anchor="middle">🤖 Autonomous agents</text>
|
|
259
|
+
</g>
|
|
260
|
+
|
|
261
|
+
<!-- app server -->
|
|
262
|
+
<rect x="280" y="70" width="180" height="120" rx="12" fill="url(#boxg)" stroke="#2c4a5e"/>
|
|
263
|
+
<text x="370" y="98" text-anchor="middle" fill="#5ec8ff" font-family="monospace" font-size="12" font-weight="700">CTM / WALL-E</text>
|
|
264
|
+
<text x="370" y="120" text-anchor="middle" fill="#e6edf3" font-family="sans-serif" font-size="13">Node app server</text>
|
|
265
|
+
<text x="370" y="142" text-anchor="middle" fill="#9aa7b8" font-family="sans-serif" font-size="12">SSE · PTY · queue</text>
|
|
266
|
+
<rect x="300" y="152" width="140" height="26" rx="6" fill="#0a1710" stroke="#26503a"/>
|
|
267
|
+
<text x="370" y="170" text-anchor="middle" fill="#7ee787" font-family="monospace" font-size="11">db-async seam (await)</text>
|
|
268
|
+
|
|
269
|
+
<!-- pooler -->
|
|
270
|
+
<rect x="510" y="98" width="96" height="64" rx="10" fill="url(#boxg)" stroke="#3a3050"/>
|
|
271
|
+
<text x="558" y="126" text-anchor="middle" fill="#9d7bff" font-family="monospace" font-size="11" font-weight="700">pgbouncer</text>
|
|
272
|
+
<text x="558" y="144" text-anchor="middle" fill="#9aa7b8" font-family="sans-serif" font-size="11">pool</text>
|
|
273
|
+
|
|
274
|
+
<!-- the spark box -->
|
|
275
|
+
<rect x="470" y="220" width="420" height="220" rx="14" fill="none" stroke="#3a2e5a" stroke-dasharray="6 5"/>
|
|
276
|
+
<text x="490" y="246" fill="#9d7bff" font-family="monospace" font-size="12" font-weight="700">DGX SPARK · 128 GB UNIFIED MEMORY</text>
|
|
277
|
+
|
|
278
|
+
<rect x="492" y="262" width="180" height="70" rx="10" fill="url(#boxg)" stroke="#2c3e6e"/>
|
|
279
|
+
<text x="582" y="288" text-anchor="middle" fill="#7aa2ff" font-family="monospace" font-size="12" font-weight="700">PostgreSQL</text>
|
|
280
|
+
<text x="582" y="308" text-anchor="middle" fill="#e6edf3" font-family="sans-serif" font-size="12">MVCC · JSONB</text>
|
|
281
|
+
<text x="582" y="324" text-anchor="middle" fill="#9aa7b8" font-family="sans-serif" font-size="11">tsvector + GIN (FTS)</text>
|
|
282
|
+
|
|
283
|
+
<rect x="690" y="262" width="180" height="70" rx="10" fill="url(#boxg)" stroke="#3a3050"/>
|
|
284
|
+
<text x="780" y="288" text-anchor="middle" fill="#9d7bff" font-family="monospace" font-size="12" font-weight="700">pgvector / VectorChord</text>
|
|
285
|
+
<text x="780" y="308" text-anchor="middle" fill="#e6edf3" font-family="sans-serif" font-size="12">halfvec · HNSW</text>
|
|
286
|
+
<text x="780" y="324" text-anchor="middle" fill="#9aa7b8" font-family="sans-serif" font-size="11">GPU index build (cuVS)</text>
|
|
287
|
+
|
|
288
|
+
<rect x="492" y="350" width="378" height="72" rx="10" fill="url(#boxg)" stroke="#3a4a2e"/>
|
|
289
|
+
<text x="681" y="376" text-anchor="middle" fill="#7ee787" font-family="monospace" font-size="12" font-weight="700">BLACKWELL GPU</text>
|
|
290
|
+
<text x="681" y="396" text-anchor="middle" fill="#e6edf3" font-family="sans-serif" font-size="12.5">Batch embeddings · local LLM (judge / classifiers / coding) · GPU ANN</text>
|
|
291
|
+
<text x="681" y="414" text-anchor="middle" fill="#9aa7b8" font-family="sans-serif" font-size="11">shares the same 128 GB — no PCIe copy between DB cache, index, and weights</text>
|
|
292
|
+
|
|
293
|
+
<!-- arrows -->
|
|
294
|
+
<g stroke="#5a6b80" stroke-width="1.6" fill="none" marker-end="url(#arr)">
|
|
295
|
+
<path d="M190 68 H276"/>
|
|
296
|
+
<path d="M190 126 H276"/>
|
|
297
|
+
<path d="M190 184 C 240 184, 250 150, 276 150"/>
|
|
298
|
+
<path d="M460 130 H506"/>
|
|
299
|
+
<path d="M558 162 V 240 H 560"/>
|
|
300
|
+
<path d="M672 297 H 686" />
|
|
301
|
+
</g>
|
|
302
|
+
<text x="232" y="60" fill="#9aa7b8" font-family="monospace" font-size="10">HTTPS / SSE</text>
|
|
303
|
+
</svg>
|
|
304
|
+
</div>
|
|
305
|
+
<figcaption>One async seam, one pool, one box. Clients (incl. agents) are symmetric peers; GPU subsystems sit in the same memory as the DB.</figcaption>
|
|
306
|
+
</figure>
|
|
307
|
+
|
|
308
|
+
<!-- ───────────────────────────── 06 ───────────────────────────── -->
|
|
309
|
+
<h2 id="gpu"><span class="n">06</span>What the GPU actually buys you</h2>
|
|
310
|
+
<p class="lead">Be specific — a GPU doesn't speed up transactional reads. It helps exactly two of our subsystems, both of which are real bottlenecks at scale.</p>
|
|
311
|
+
|
|
312
|
+
<div class="grid2">
|
|
313
|
+
<div class="card">
|
|
314
|
+
<h4><span class="dot" style="background:var(--gpu)"></span>Vector search & index builds</h4>
|
|
315
|
+
<p><b>cuVS</b> (RAPIDS) runs CAGRA / IVF-PQ / IVF-flat ANN on the GPU. <b>VectorChord</b> indexes ~100M vectors in ~20 min on CPU; GPU build via EDB PGPU cuts that further. For a growing brain, index <em>rebuild</em> time is the pain — this is where the GPU earns its place.</p>
|
|
316
|
+
</div>
|
|
317
|
+
<div class="card">
|
|
318
|
+
<h4><span class="dot" style="background:var(--accent2)"></span>Embeddings & local inference</h4>
|
|
319
|
+
<p>Batch embedding generation is embarrassingly parallel — GPU throughput dwarfs CPU. And the approval judge / intent classifier / cheap coding turns could run on a <em>local</em> Blackwell-hosted model instead of round-tripping to cloud Claude, for privacy + zero marginal cost on the cheap turns.</p>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div class="callout">
|
|
324
|
+
<div class="h">Where the GPU does nothing</div>
|
|
325
|
+
<p>The freeze-relevant path — thousands of tiny per-session metadata reads — is <strong>not</strong> GPU work. That's won by the async seam + a read cache, full stop. Don't let the shiny hardware distract from the fact that <em>Phase 0 alone fixes most of the freezes</em>. The GPU is for the vector + inference frontier, not for making CTM feel snappy.</p>
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<!-- ───────────────────────────── 07 ───────────────────────────── -->
|
|
329
|
+
<h2 id="sizing"><span class="n">07</span>Capacity & sizing — rough numbers</h2>
|
|
330
|
+
<p class="lead">Order-of-magnitude only, to calibrate ambition. The honest takeaway: today's load doesn't need a Spark; a Spark only makes sense if local inference becomes a first-class part of the product.</p>
|
|
331
|
+
|
|
332
|
+
<table>
|
|
333
|
+
<thead><tr><th>Workload</th><th>Today's scale</th><th>Fits in…</th></tr></thead>
|
|
334
|
+
<tbody>
|
|
335
|
+
<tr><td>CTM transactional state</td><td>~35 tables, sessions+messages</td><td class="yes">Trivially in 128 GB RAM; would fit a Raspberry Pi's Postgres, honestly</td></tr>
|
|
336
|
+
<tr><td>Wall-E brain</td><td>~1–2.6 GB (int8 FTS-optimized)</td><td class="yes">Entirely in shared buffers; halfvec keeps it small</td></tr>
|
|
337
|
+
<tr><td>Embedding index</td><td>brain-scale vectors</td><td class="yes">In-memory HNSW; GPU build is a latency win, not a capacity need</td></tr>
|
|
338
|
+
<tr><td>Local inference</td><td>gemma-class today</td><td class="meh">This is the <em>only</em> thing that wants the Blackwell GPU — and only if you move judge/classifier/coding turns local</td></tr>
|
|
339
|
+
</tbody>
|
|
340
|
+
</table>
|
|
341
|
+
|
|
342
|
+
<div class="callout warn">
|
|
343
|
+
<div class="h">Sizing reality check</div>
|
|
344
|
+
<p>The database half of this never needed a supercomputer — Postgres on a $5/mo VM or a Mac mini handles CTM+Wall-E's state for one user with room to spare. <strong>The Spark is justified by the inference half, not the data half.</strong> If you're not moving meaningful LLM work local, a hosted Postgres (Fly/Neon/Supabase) from the original plan is the rational stop point.</p>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
<!-- ───────────────────────────── 08 ───────────────────────────── -->
|
|
348
|
+
<h2 id="phasing"><span class="n">08</span>How this extends the Phase 0–5 plan</h2>
|
|
349
|
+
<p class="lead">Nothing here replaces the existing spec — it adds an optional fork at the end. The first five phases are unchanged and remain independently valuable.</p>
|
|
350
|
+
|
|
351
|
+
<table>
|
|
352
|
+
<thead><tr><th>Phase</th><th>From the original plan</th><th>Concurrency / Spark overlay</th></tr></thead>
|
|
353
|
+
<tbody>
|
|
354
|
+
<tr><td><b>0</b> <span class="tag now">shipped</span></td><td>Async data-access seam on SQLite</td><td>This is the prerequisite for <em>all</em> concurrency. Already on <code>feat/db-async-seam</code>.</td></tr>
|
|
355
|
+
<tr><td><b>1–2</b></td><td>Schema port + FTS→tsvector, sqlite-vec→pgvector</td><td>Choose <code>pgvector</code> <em>or</em> <code>VectorChord</code> at this step — VectorChord if GPU index builds are on the table.</td></tr>
|
|
356
|
+
<tr><td><b>3–4</b></td><td>ETL + parity tests, cutover, retire SQLite machinery</td><td>Unchanged. Pooling (pgbouncer) is added here for multi-client readiness.</td></tr>
|
|
357
|
+
<tr><td><b>5</b></td><td>Enable remote/multi-device + read cache + auth</td><td>This is where concurrency becomes <em>real</em>. Gate on p50/p99 latency parity.</td></tr>
|
|
358
|
+
<tr><td><b>6</b> <span class="tag far">new, optional</span></td><td>—</td><td><b>Co-locate on owned compute (Spark).</b> Move GPU embedding + local inference onto the box; hybrid-route cheap/private turns local, frontier turns to cloud.</td></tr>
|
|
359
|
+
</tbody>
|
|
360
|
+
</table>
|
|
361
|
+
|
|
362
|
+
<!-- ───────────────────────────── 09 ───────────────────────────── -->
|
|
363
|
+
<h2 id="risks"><span class="n">09</span>Risks & honest caveats</h2>
|
|
364
|
+
<div class="grid2">
|
|
365
|
+
<div class="card"><h4><span class="dot" style="background:var(--bad)"></span>Single point of failure</h4><p>Co-locating everything on one box means one box's downtime takes the whole stack. A file-based SQLite that travels with the app has a real resilience advantage for a solo user.</p></div>
|
|
366
|
+
<div class="card"><h4><span class="dot" style="background:var(--bad)"></span>Arm64 + DGX OS quirks</h4><p>Spark is Arm + a custom Ubuntu (DGX OS). <code>better-sqlite3</code>/native-module ABI lessons apply doubly; pin Node, verify pgvector/VectorChord/cuVS builds for Arm + GB10.</p></div>
|
|
367
|
+
<div class="card"><h4><span class="dot" style="background:var(--warn)"></span>Latency can still regress feel</h4><p>Networked DB + agents hammering it = lag unless the read cache + batching land. This is the make-or-break from the original plan, unchanged.</p></div>
|
|
368
|
+
<div class="card"><h4><span class="dot" style="background:var(--warn)"></span>Overkill risk</h4><p>For one user with cloud LLM calls, a Spark is expensive idle silicon. Don't buy hardware to solve a software (async) problem.</p></div>
|
|
369
|
+
<div class="card"><h4><span class="dot" style="background:var(--warn)"></span>Ops surface grows</h4><p>Postgres needs backups, vacuum/autovacuum tuning, connection security. A GPU node adds driver/CUDA lifecycle on top.</p></div>
|
|
370
|
+
<div class="card"><h4><span class="dot" style="background:var(--accent2)"></span>But the seam is free insurance</h4><p>Phase 0 is done and reversible. Every later decision — hosted PG, Spark, or stay on SQLite — is now <em>open</em> rather than foreclosed. That optionality is the real win today.</p></div>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<!-- ───────────────────────────── 10 ───────────────────────────── -->
|
|
374
|
+
<h2 id="verdict"><span class="n">10</span>Decision matrix: when is this worth it?</h2>
|
|
375
|
+
<table>
|
|
376
|
+
<thead><tr><th>Your situation</th><th>Right move</th><th>Why</th></tr></thead>
|
|
377
|
+
<tbody>
|
|
378
|
+
<tr><td>Solo user, freezes are the only pain</td><td><b>Stop at Phase 0</b> (+ read cache)</td><td>The async seam captures most freeze relief on SQLite. No engine change needed.</td></tr>
|
|
379
|
+
<tr><td>Want phone + laptop on the same brain</td><td><b>Phases 1–5, hosted Postgres</b></td><td>Multi-device forces a server DB; Fly/Neon/Supabase is the low-ops path.</td></tr>
|
|
380
|
+
<tr><td>Many concurrent agents writing state</td><td><b>Phases 1–5 + pooling</b></td><td>MVCC + pgbouncer is exactly the model genuine write concurrency needs.</td></tr>
|
|
381
|
+
<tr><td>Heavy local inference + privacy + always-on, on owned hardware</td><td><b>Phase 6 — the Spark</b></td><td>The <em>only</em> scenario where co-location pays for itself. Unified memory + GB10 GPU vector + local LLM is a genuinely strong fit.</td></tr>
|
|
382
|
+
<tr><td>Just exploring</td><td><b>Keep the seam, watch VectorChord/cuVS</b></td><td>You've bought optionality cheaply. Decide when a real driver (a second device, or local-inference ambition) appears.</td></tr>
|
|
383
|
+
</tbody>
|
|
384
|
+
</table>
|
|
385
|
+
|
|
386
|
+
<div class="callout good">
|
|
387
|
+
<div class="h">Bottom line</div>
|
|
388
|
+
<p>The Spark idea is <strong>not a fantasy</strong> — the hardware and the GPU-Postgres software (EDB PGPU on GB10, VectorChord, cuVS) line up unusually well for a workload that's one-third state, one-third vectors, one-third inference. But it answers a question we haven't yet asked the product: <em>do we want meaningful LLM inference to run on hardware we own?</em> If yes, this is the destination. If no, hosted Postgres is the honest stopping point, and Phase 0 already bought us most of the freeze relief regardless.</p>
|
|
389
|
+
</div>
|
|
390
|
+
|
|
391
|
+
<hr>
|
|
392
|
+
|
|
393
|
+
<footer>
|
|
394
|
+
<p class="src"><b>Sources</b><br>
|
|
395
|
+
· <a href="https://www.nvidia.com/en-us/products/workstations/dgx-spark/">NVIDIA DGX Spark — product page</a><br>
|
|
396
|
+
· <a href="https://docs.nvidia.com/dgx/dgx-spark/hardware.html">DGX Spark User Guide — Hardware Overview</a><br>
|
|
397
|
+
· <a href="https://www.microcenter.com/product/699008/nvidia-dgx-spark">Micro Center — DGX Spark specs (GB10, 20-core Arm, 128 GB LPDDR5X, 4 TB)</a><br>
|
|
398
|
+
· <a href="https://www.enterprisedb.com/docs/edb-postgres-ai/latest/ai-factory/pgpu/">EDB Postgres AI — PGPU GPU-accelerated vector index build (lists GB10 support)</a><br>
|
|
399
|
+
· <a href="https://github.com/supervc-stack/VectorChord">VectorChord — scalable disk-friendly vector search in Postgres (successor to pgvecto.rs)</a><br>
|
|
400
|
+
· <a href="https://rapids.ai/cuvs/">RAPIDS cuVS — GPU ANN (CAGRA, IVF-PQ, IVF-flat)</a><br>
|
|
401
|
+
· <a href="https://github.com/pgvector/pgvector">pgvector — halfvec, HNSW</a></p>
|
|
402
|
+
<p style="margin-top:18px;color:#6b7888">CTM + Wall-E architecture discussion · companion to the Postgres migration spec (Phases 0–5) · 2026-06-28 · exploratory, not a commitment.</p>
|
|
403
|
+
</footer>
|
|
404
|
+
|
|
405
|
+
</div>
|
|
406
|
+
</body>
|
|
407
|
+
</html>
|
|
@@ -471,15 +471,17 @@
|
|
|
471
471
|
<section id="editor">
|
|
472
472
|
<div class="sec-head"><span class="sec-num">04</span><h2>Editor — author what a prompt really is</h2></div>
|
|
473
473
|
<p class="sec-sub">
|
|
474
|
-
Phase 2 flagship. Prompts here are templated markdown sent to coding agents
|
|
475
|
-
|
|
476
|
-
|
|
474
|
+
Phase 2 flagship. Prompts here are templated markdown sent to coding agents — so the editor ships
|
|
475
|
+
<b>both</b> a rich WYSIWYG mode <b>(default)</b> and a Markdown mode, with a one-click switch in the
|
|
476
|
+
toolbar. Either mode highlights <code>{{variables}}</code>, offers a live preview, and shows a live
|
|
477
|
+
token meter; switching is lossless (content round-trips HTML ↔ markdown).
|
|
477
478
|
</p>
|
|
478
479
|
|
|
479
480
|
<div class="mock">
|
|
480
481
|
<div class="mock-caption"><span class="dot r"></span><span class="dot y"></span><span class="dot g"></span><span class="url">localhost:3456/#prompts → Deep code review</span></div>
|
|
481
482
|
<div class="ed-toolbar">
|
|
482
|
-
<span class="seg"
|
|
483
|
+
<span class="seg" title="Editor mode — WYSIWYG is the default"><b>✎ Rich</b><b class="on"></> Markdown</b></span>
|
|
484
|
+
<span class="seg"><b>Edit</b><b>Preview</b><b class="on">Split</b></span>
|
|
483
485
|
<span class="tb">{{ }}</span>
|
|
484
486
|
<span class="tb">/ snippet</span>
|
|
485
487
|
<span class="tb">@ file</span>
|
|
@@ -520,33 +522,32 @@
|
|
|
520
522
|
<div><b>Prior art:</b> A live in-editor <b>token counter</b> is documented mainly in Google AI Studio — a genuine differentiator. The Anthropic Console "Variables window" separates template text from inputs; Claude Code's <code>!`cmd`</code> and <code>@file</code> inject live repo context. Both map directly onto what CTM prompts need.</div>
|
|
521
523
|
</div>
|
|
522
524
|
|
|
523
|
-
<h3 style="font-size:18px; margin:34px 0 4px;">
|
|
525
|
+
<h3 style="font-size:18px; margin:34px 0 4px;">Both modes, one switch</h3>
|
|
524
526
|
<div class="alt-grid">
|
|
525
527
|
<div class="alt-card rec">
|
|
526
|
-
<h4>
|
|
527
|
-
<div class="sub">
|
|
528
|
+
<h4>Rich · WYSIWYG <span class="rectag">Default</span></h4>
|
|
529
|
+
<div class="sub">The familiar editor, upgraded.</div>
|
|
528
530
|
<ul>
|
|
529
|
-
<li>
|
|
530
|
-
<li>
|
|
531
|
-
<li>Live token
|
|
532
|
-
<li><code>/</code> snippet
|
|
533
|
-
<li>
|
|
534
|
-
<li class="con">Larger build: introduce CodeMirror; migrate HTML content → markdown</li>
|
|
531
|
+
<li>Keeps <code>contenteditable</code> formatting + first-class image annotation</li>
|
|
532
|
+
<li><code>{{variables}}</code> render as inline chips</li>
|
|
533
|
+
<li>Live token/char meter + a preview toggle</li>
|
|
534
|
+
<li><code>/</code> snippet & <code>@</code> file insert</li>
|
|
535
|
+
<li>Zero learning curve — what most prompts need</li>
|
|
535
536
|
</ul>
|
|
536
537
|
</div>
|
|
537
|
-
<div class="alt-card">
|
|
538
|
-
<h4>
|
|
539
|
-
<div class="sub">
|
|
538
|
+
<div class="alt-card rec">
|
|
539
|
+
<h4>Markdown · source <span class="rectag">One click away</span></h4>
|
|
540
|
+
<div class="sub">CodeMirror-style, for power authoring.</div>
|
|
540
541
|
<ul>
|
|
541
|
-
<li>
|
|
542
|
-
<li>
|
|
543
|
-
<li>
|
|
544
|
-
<li>
|
|
545
|
-
<li
|
|
542
|
+
<li>Markdown + <code>{{variable}}</code> + <code>!`cmd`</code>/<code>@file</code> highlighting</li>
|
|
543
|
+
<li>Edit / Preview / Split sub-modes; live preview pane</li>
|
|
544
|
+
<li>Same live token meter; same <code>/</code> & <code>@</code> inserts</li>
|
|
545
|
+
<li>Exact control over whitespace & structure</li>
|
|
546
|
+
<li>Image annotation still available via paste</li>
|
|
546
547
|
</ul>
|
|
547
548
|
</div>
|
|
548
549
|
</div>
|
|
549
|
-
<p class="sec-sub" style="margin-top:18px;"><b>
|
|
550
|
+
<p class="sec-sub" style="margin-top:18px;"><b>How it works:</b> the toolbar mode switch (<code>✎ Rich | </> Markdown</code>) flips between them; <b>WYSIWYG is the default</b>. Switching is <b>lossless</b> — content round-trips through the existing <code>htmlToMarkdown</code> converter (<code class="mono">prompts.js</code>) and a markdown→HTML renderer, and the chosen mode is remembered per user. No data migration: prompts keep their stored HTML, markdown is derived on demand.</p>
|
|
550
551
|
</section>
|
|
551
552
|
|
|
552
553
|
<!-- ===================== REUSE ===================== -->
|
|
@@ -624,7 +625,7 @@
|
|
|
624
625
|
</div>
|
|
625
626
|
<div class="phase">
|
|
626
627
|
<div class="pn">Phase 2<small>Editor</small></div>
|
|
627
|
-
<div class="pbody"><h4>
|
|
628
|
+
<div class="pbody"><h4>Dual-mode editor</h4><p>Ship <b>Rich (WYSIWYG, default)</b> + <b>Markdown</b> with a lossless toolbar switch. Markdown mode adds <code>{{var}}</code> highlighting, Edit/Preview/Split, live token meter, <code>/</code> snippets. Image annotation kept in both. No content migration — markdown derived via <code>htmlToMarkdown</code>.</p></div>
|
|
628
629
|
<span class="risk med">Med</span>
|
|
629
630
|
</div>
|
|
630
631
|
<div class="phase">
|