From 251967706bb9eb1d4174dc0ccd332c3a4d4a3ada Mon Sep 17 00:00:00 2001 From: arko33 <221298156+arko33@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:10:59 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20Ghost=20City=20=E2=80=94=20zero-dep=20l?= =?UTF-8?q?ive=20playground=20served=20by=20the=20recorder=20at=20/city?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ghost/ghost.mjs | 119 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/packages/ghost/ghost.mjs b/packages/ghost/ghost.mjs index f740e1d..9987e61 100644 --- a/packages/ghost/ghost.mjs +++ b/packages/ghost/ghost.mjs @@ -65,7 +65,7 @@ function studioHtml(base) {

Checkpoints — shadow commits

Runtime samples

+locals: /session (JSON) · city view · events target for the OpenCode adapter: ${base}/events `; } +// Ghost City — a zero-dependency live playground served by the recorder +// itself, so `ghost watch` works like prisma studio: install once, run it in +// any project, open the URL — no repo clone, no "npm run dev" required. +// Towers are facts of the recording: files actually touched (churn height +// when a git patch exists, flat tiles when not — never invented data). +function cityHtml() { + return ` + +Ghost City — live playground + +

Ghost City — recording live

…
+
+ +
+ +`; +} + // ── helpers ────────────────────────────────────────────────────────────────── // Parse a unified diff into per-file churn (added+deleted lines) used as the // 3D city "height" — so towers stay a fact of the recording, never invented. @@ -211,6 +318,11 @@ async function cmdWatch() { res.end(studioHtml(eventsBase)); return; } + if (req.method === "GET" && req.url === "/city") { + res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }); + res.end(cityHtml()); + return; + } if (req.method === "GET" && req.url === "/session") { res.writeHead(200, { "content-type": "application/json; charset=utf-8", @@ -316,8 +428,9 @@ async function cmdWatch() { console.log(` repo ${repo}`); if (!session.head) console.log(` git none — file recording only (run git init to enable shadow-git checkpoints)`); console.log(` app ${appUrl}`); - console.log(` studio ${eventsBase} ← open in browser: live turns, checkpoints, samples`); - console.log(` replay local dashboard: /playground?live=1 (identical to the published demo)`); + console.log(` studio ${eventsBase} ← detail: turns, checkpoints, samples`); + console.log(` city ${eventsBase}/city ← playground kota live (tanpa npm run dev)`); + console.log(` replay full 3D dashboard: repo → npm run dev → /playground?live=1`); console.log(` adapter ${eventsBase}/events (OpenCode plugin target)`); console.log(` sync ${sync}${sync === "off" ? " (local-only) — run: ghost setup to enable" : ""}`); console.log(` press Ctrl+C to stop & save\n`);