From 79d26f0fbd758379a446d95706dc2c9272951ca4 Mon Sep 17 00:00:00 2001 From: Den <2119348+dzianisv@users.noreply.github.com> Date: Sun, 21 Jun 2026 22:01:05 -0700 Subject: [PATCH] fix(sessions): scope default to server CWD, not $HOME (#32) (#33) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent sessions disappeared from the list when opencode serve was launched outside $HOME (e.g. ~/workspace/opencode). The list path scoped to server.home, but opencode-server resolves x-opencode-directory to a project id by exact-match, not subtree prefix. $HOME mapped to the synthetic 'global' project, which never contained the user's workspace sessions. Change the single-source-of-truth rule to return null (no scope header) when the connection has no explicit directory. The server then uses its own CWD project — the same project sessions are actually created in. Both list and create paths still derive from sessionScopeDirectory, so #10's drift cure is preserved. Verified against 100.108.64.76:4096: no header returns the recent workspace sessions (Opencode npm install, autopilot_exit, ...); header=$HOME returns only the empty global project. Closes #32 --- src/stores/sessionScope.test.ts | 17 +++++++++++++---- src/stores/sessionScope.ts | 18 ++++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/stores/sessionScope.test.ts b/src/stores/sessionScope.test.ts index 98dc3bd..e95eb0d 100644 --- a/src/stores/sessionScope.test.ts +++ b/src/stores/sessionScope.test.ts @@ -3,10 +3,12 @@ import assert from "node:assert/strict" import { sessionScopeDirectory } from "./sessionScope.ts" // Bug #10 regression guard: list and create must resolve to the SAME scope. -// These cases pin the shared rule both call sites rely on. +// Bug #32 regression guard: the default scope must be "no header" (null), not +// the server's home directory. The home dir resolves to the "global" project on +// the opencode server and hides real workspace sessions. -test("no explicit directory + known home -> scope to home", () => { - assert.equal(sessionScopeDirectory(false, "/home/user"), "/home/user") +test("no explicit directory + known home -> default client (null), home ignored (#32)", () => { + assert.equal(sessionScopeDirectory(false, "/home/user"), null) }) test("no explicit directory + unknown home -> default client (null)", () => { @@ -20,7 +22,7 @@ test("explicit directory -> default client (null), home ignored", () => { assert.equal(sessionScopeDirectory(true, null), null) }) -test("create and list resolve identically across all inputs (no drift)", () => { +test("create and list resolve identically across all inputs (no drift, #10)", () => { for (const hasDir of [true, false]) { for (const home of ["/home/user", null, undefined, ""]) { const listScope = sessionScopeDirectory(hasDir, home) @@ -29,3 +31,10 @@ test("create and list resolve identically across all inputs (no drift)", () => { } } }) + +test("server directory != home: rule returns null so server uses its CWD project (#32)", () => { + // Reproduces the real-world setup: server launched in ~/workspace/opencode + // while $HOME is /home/azureuser. Old rule returned "/home/azureuser" (global + // project, empty). New rule returns null so server uses its CWD project. + assert.equal(sessionScopeDirectory(false, "/home/azureuser"), null) +}) diff --git a/src/stores/sessionScope.ts b/src/stores/sessionScope.ts index 2204567..069093d 100644 --- a/src/stores/sessionScope.ts +++ b/src/stores/sessionScope.ts @@ -6,11 +6,21 @@ // a freshly created session was invisible. Both call sites now derive their client // from this one function, so they cannot disagree again. // +// Bug #32 ("recent sessions missing"): the previous rule scoped to the server's +// home directory when no explicit directory was set. opencode-server resolves the +// x-opencode-directory header to a project id by exact-match, NOT subtree prefix. +// $HOME typically maps to the synthetic "global" project, which never contains +// the user's real workspace sessions (those live under e.g. ~/workspace/foo, a +// different project id). The list looked empty even when sessions existed. +// // Rule: when the active connection pins an explicit directory, use the default -// client (it is already scoped to that directory). Otherwise, if we know the -// server's home directory, scope to it. If home is unknown, fall back to default. +// client (it is already scoped to that directory). Otherwise, send no scope at +// all so the server uses its own CWD — i.e. the project where opencode serve was +// launched, which is the project the user actually works in. The `home` argument +// is accepted for backward compatibility but intentionally ignored. -export function sessionScopeDirectory(hasExplicitDirectory: boolean, home: string | null | undefined): string | null { +export function sessionScopeDirectory(hasExplicitDirectory: boolean, _home?: string | null | undefined): string | null { + void _home if (hasExplicitDirectory) return null - return home ? home : null + return null }