From 72255cc32ccfd5261c39647949590367a8b86242 Mon Sep 17 00:00:00 2001
From: arko33 <221298156+arko33@users.noreply.github.com>
Date: Thu, 22 Oct 2026 01:09:58 +0700
Subject: [PATCH 1/2] fix(landing): proof section reflects the live 24-test
suite (23 backend + 1 integration)
---
src/components/site/LandingPage.tsx | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/components/site/LandingPage.tsx b/src/components/site/LandingPage.tsx
index c7a1c69..7eba6b4 100644
--- a/src/components/site/LandingPage.tsx
+++ b/src/components/site/LandingPage.tsx
@@ -799,7 +799,8 @@ export default function LandingPage() {
- 13 backend tests. Every pull request. The deployed URL.
+ 23 backend tests + 1 integration flow. Every pull request.
+ The deployed URL.
>
@@ -914,16 +915,19 @@ export default function LandingPage() {
Required check
-
- /13
+
+ /24
Green · suite passes
- - Runs on every pull request against the deployed URL.
- - A red suite blocks the merge.
+ - 24 tests: 23 backend tests + 1 integration flow.
+ -
+ The PR check reruns the backend set on every pull request,
+ against the deployed URL.
+
-
PR #1 shipped a BOLA hole. PR #2 fixed it. Same suite, green.
@@ -935,7 +939,7 @@ export default function LandingPage() {
- PR #2 · 13/13
+ PR #2 · fixed · suite green
@@ -1084,7 +1088,7 @@ export default function LandingPage() {
- Built for TestSprite Season 4 · 13/13
+ Built for TestSprite Season 4 · 24-test suite
required check
From 08b8cc3931e024e41d4847476aed4c49a4b6dcb6 Mon Sep 17 00:00:00 2001
From: arko33 <221298156+arko33@users.noreply.github.com>
Date: Thu, 22 Oct 2026 01:16:14 +0700
Subject: [PATCH 2/2] =?UTF-8?q?fix:=20real-user=20journey=20=E2=80=94=20qu?=
=?UTF-8?q?iet=20non-git=20dirs,=20mkdir=20for=20the=20OpenCode=20adapter,?=
=?UTF-8?q?=20app-run=20note?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Real-user test in a non-git project surfaced: stray 'fatal: not a git repository' on stderr (git calls now suppress it + friendly hint lines), the OpenCode adapter curl failed without the plugin folder (mkdir command now typed in the landing terminal), and localhost refused because ghost watch records and never starts the app (copy now states the app must run separately). Also fixes the garbled usage line in install.sh.
---
README.md | 11 ++++++++---
packages/ghost/ghost.mjs | 2 ++
packages/ghost/install.sh | 2 +-
packages/ghost/lib/shadowgit.mjs | 4 ++--
src/components/site/LandingPage.tsx | 4 ++--
src/components/site/Terminal.tsx | 1 +
6 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 885b5b2..9d8711c 100644
--- a/README.md
+++ b/README.md
@@ -433,9 +433,14 @@ curl -o .opencode/plugins/ghost.ts \
The adapter reports `turn.started` (the prompt admission — the authoritative
turn boundary) and `turn.completed` to the local recorder on
-`127.0.0.1:5417/events`. No plugin? Recording still works — the filesystem
-watcher + runtime probes capture everything from the outside and turns are
-marked **estimated, never invented**.
+`127.0.0.1:5417/events`. Note: `ghost watch` **recording** — it does not start
+your app. Run your project as usual (e.g. `npm run dev`) in another terminal so
+the runtime probes have something to measure.
+
+No plugin? Recording still works — the filesystem watcher + runtime probes
+capture everything from the outside and turns are marked **estimated, never
+invented**. Not a git repository? File recording still works; run `git init`
+to unlock shadow-git checkpoints.
## 🛠️ Stack
diff --git a/packages/ghost/ghost.mjs b/packages/ghost/ghost.mjs
index 2a8f079..0fb5728 100644
--- a/packages/ghost/ghost.mjs
+++ b/packages/ghost/ghost.mjs
@@ -175,6 +175,7 @@ async function cmdWatch() {
console.log(`\n ● Ghost recorder is live`);
console.log(` session ${session.id}`);
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(` adapter ${eventsBase}/events (OpenCode plugin target)`);
console.log(` sync ${sync}${sync === "off" ? " (local-only) — run: ghost setup to enable" : ""}`);
@@ -210,6 +211,7 @@ function cmdStatus() {
const head = shadow.currentHead(ROOT);
console.log(`repo ${ROOT}`);
console.log(`head ${head ? head.slice(0, 10) : "(no git)"}`);
+ if (!head) console.log(` (not a git repo — run git init to enable shadow-git checkpoints)`);
console.log(`cloud ${config.cloudUrl}${creds ? " (paired)" : " (NOT paired)"}`);
console.log(`sync ${creds ? config.sync : "off (local-only)"}`);
console.log(`settings .ghost/config.json — secrets handled per README policy`);
diff --git a/packages/ghost/install.sh b/packages/ghost/install.sh
index ef9636e..19f8c8e 100644
--- a/packages/ghost/install.sh
+++ b/packages/ghost/install.sh
@@ -60,7 +60,7 @@ echo " shim : ${GHOST_BIN}/ghost"
echo ""
echo " Usage (from ANY project directory):"
echo " ghost status # summary of repo + cloud pairing"
-echo " ghost watch # record/live session View README"
+echo " ghost watch # record a live session (README: full guide)"
echo " ghost sessions # list recorded sessions"
echo " ghost setup # optionally pair with Ghost Cloud"
echo ""
diff --git a/packages/ghost/lib/shadowgit.mjs b/packages/ghost/lib/shadowgit.mjs
index 4d37e8f..1c80b67 100644
--- a/packages/ghost/lib/shadowgit.mjs
+++ b/packages/ghost/lib/shadowgit.mjs
@@ -22,7 +22,7 @@ export function commitSnapshot(repo, message = "ghost checkpoint") {
const env = { ...process.env, GIT_INDEX_FILE: idx };
const git = (args, extraEnv = {}) =>
- execFileSync("git", args, { cwd: repo, env: { ...env, ...extraEnv }, encoding: "utf8" }).trim();
+ execFileSync("git", args, { cwd: repo, env: { ...env, ...extraEnv }, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
try { git(["read-tree", "HEAD"]); } catch { /* empty repo without HEAD */ }
git(["add", "-A"]);
@@ -56,6 +56,6 @@ export function showFile(repo, sha, filePath) {
}
export function currentHead(repo) {
- try { return execFileSync("git", ["rev-parse", "HEAD"], { cwd: repo, encoding: "utf8" }).trim(); }
+ try { return execFileSync("git", ["rev-parse", "HEAD"], { cwd: repo, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim(); }
catch { return null; }
}
diff --git a/src/components/site/LandingPage.tsx b/src/components/site/LandingPage.tsx
index 7eba6b4..216d23f 100644
--- a/src/components/site/LandingPage.tsx
+++ b/src/components/site/LandingPage.tsx
@@ -976,12 +976,12 @@ export default function LandingPage() {
{
n: "02",
t: "Connect OpenCode (Mode A)",
- d: "Copy the one-file adapter into .opencode/plugins/ghost.ts - OpenCode then reports every turn boundary to the recorder, so the timeline uses real turn ids.",
+ d: "Two commands (typed by the terminal on the right): create the plugin folder, copy the one-file adapter in. OpenCode then reports every turn boundary to the recorder, so the timeline uses real turn ids.",
},
{
n: "03",
t: "Record any session",
- d: "Run ghost watch in your project. With the plugin installed, turns stream live; with any other agent (Cursor, Claude Code, a human) the filesystem watcher + runtime probes record everything from the outside - turns marked estimated, never invented.",
+ d: "Run ghost watch in your project, and run your app yourself (npm run dev etc.) - the recorder probes its /api/health. With the plugin, turns stream live; with any other agent (Cursor, Claude Code, a human) the filesystem watcher + runtime probes record everything from the outside - turns marked estimated, never invented.",
},
{
n: "04",
diff --git a/src/components/site/Terminal.tsx b/src/components/site/Terminal.tsx
index 61f6cd2..4c988fd 100644
--- a/src/components/site/Terminal.tsx
+++ b/src/components/site/Terminal.tsx
@@ -6,6 +6,7 @@ import { useInView, useReducedMotion } from "./hooks";
const COMMANDS = [
"curl -fsSL https://raw.githubusercontent.com/arko33/ghostinthecodebase/main/packages/ghost/install.sh | bash",
+ "mkdir -p .opencode/plugins",
"curl -o .opencode/plugins/ghost.ts https://raw.githubusercontent.com/arko33/ghostinthecodebase/main/packages/opencode-plugin/index.ts",
"ghost watch --repo . --app-url http://localhost:3000",
"ghost status",