Fix canvas repo detection and shrink oversized preview images (#2227)

Canvas extensions (accessibility-kanban, where-was-i) resolved git state
against the extension's install directory or the session-state folder
instead of the repo the session was opened in. This broke repo/branch
detection for user-scoped installs and worktrees ("unknown/unknown",
"detached HEAD"). Both now read the active session's working directory
from the canvas request context on open and on each action, so they
follow whichever project/worktree opened them.

where-was-i also re-gathers context on open when the saved branch is
blank, so it never opens stuck on stale data.

Also compress oversized extension preview images (pngquant, with a mild
resize for the photographic arcade-canvas art) so every preview.png is
comfortably under the installer's inline-byte cap that was blocking
release-notes-showcase from installing.

Update release-notes-showcase author to Kayla Cinnamon.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
James Montemagno
2026-07-06 17:54:51 -07:00
committed by GitHub
parent 969d814f7e
commit e370b97107
9 changed files with 68 additions and 26 deletions
+30 -8
View File
@@ -14,11 +14,28 @@ const contextCache = new Map(); // instanceId → contextData
const isWindows = process.platform === "win32";
// Derive repo root from extension location (.github/extensions/where-was-i/)
// Fallback repo root derived from extension location. Only used when the
// session's real working directory is unavailable (see captureCwd below).
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const REPO_ROOT = join(__dirname, "..", "..", "..");
// The canvas request context reports the active session's working directory —
// the actual repo checkout or worktree the user opened the canvas in. This is
// what git commands must run against; REPO_ROOT (the extension's install dir)
// and session.workspacePath (the session-state folder) are NOT the repo, which
// is why the board previously showed an empty branch as "detached HEAD".
let workspaceCwd = null;
function captureCwd(ctx) {
const dir = ctx?.session?.workingDirectory;
if (typeof dir === "string" && dir.trim()) workspaceCwd = dir;
}
function repoCwd() {
return workspaceCwd || REPO_ROOT;
}
// --- Shell helpers ---
function run(cmd, cwd) {
@@ -34,7 +51,7 @@ function run(cmd, cwd) {
}
async function gatherContext(cwd) {
cwd = cwd || REPO_ROOT;
cwd = cwd || repoCwd();
const authorCmd = isWindows
? 'git log --oneline -5 --format="%h %s" --author="$(git config user.name)"'
: 'git log --oneline -5 --format="%h %s" --author="$(git config user.name)"';
@@ -605,7 +622,7 @@ async function startServer(instanceId, sessionRef, cwd, workspacePath) {
}
if (url.pathname === "/refresh" && req.method === "POST") {
const data = await gatherContext(cwd);
const data = await gatherContext(repoCwd());
contextCache.set(instanceId, data);
await saveContext(workspacePath, data);
broadcast(instanceId, data);
@@ -672,7 +689,8 @@ const session = await joinSession({
name: "refresh",
description: "Re-gather all git/project context and push updates to the canvas",
handler: async (ctx) => {
const data = await gatherContext(REPO_ROOT);
captureCwd(ctx);
const data = await gatherContext(repoCwd());
contextCache.set(ctx.instanceId, data);
if (sessionRef) await saveContext(sessionRef.workspacePath, data);
broadcast(ctx.instanceId, data);
@@ -713,16 +731,20 @@ const session = await joinSession({
},
],
open: async (ctx) => {
captureCwd(ctx);
let entry = servers.get(ctx.instanceId);
if (!entry) {
entry = await startServer(ctx.instanceId, sessionRef, REPO_ROOT, sessionRef?.workspacePath);
entry = await startServer(ctx.instanceId, sessionRef, repoCwd(), sessionRef?.workspacePath);
servers.set(ctx.instanceId, entry);
}
// Load persisted context or gather fresh
// Load persisted context or gather fresh. Re-gather when the
// saved context is missing or has no branch (e.g. it was saved
// before the working directory was known), so the board never
// opens stuck on a stale "detached HEAD".
let data = await loadContext(sessionRef?.workspacePath);
if (!data) {
data = await gatherContext(REPO_ROOT);
if (!data || !data.branch) {
data = await gatherContext(repoCwd());
await saveContext(sessionRef?.workspacePath, data);
}
contextCache.set(ctx.instanceId, data);