From ba42f2424605f7172bde26294ae16e7f455a5373 Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Thu, 28 May 2026 16:37:41 +0200 Subject: [PATCH] fix(pi): show actionable status for ambiguous project errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the generic '· error' status bar label with '· ambiguous project' when the underlying failure is an ambiguous project detection (multiple git repos in cwd). Adds `errorStatusLabel()` to map known error patterns to actionable labels so users can distinguish backend errors from project resolution problems. Closes #384 --- plugin/pi/README.md | 8 ++++++++ plugin/pi/index.ts | 7 ++++++- plugin/pi/test/index-source.test.mjs | 12 ++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/plugin/pi/README.md b/plugin/pi/README.md index c67b31c9..1468febf 100644 --- a/plugin/pi/README.md +++ b/plugin/pi/README.md @@ -112,6 +112,13 @@ Pi-native compact tools use the same HTTP server path as event capture, includin Normal memory activity also updates the status bar with short progress/result text such as `🧠 engram · search…` and `🧠 engram · ✓ 4 results`. The extension does not use notifications for normal memory operations. +When a tool call fails because Engram cannot determine which project to use, the status bar shows an actionable label instead of the generic `error`: + +| Status bar label | Meaning | +| -------------------------- | ----------------------------------------------------------------------------------------------------- | +| `🧠 repos · ambiguous project` | Pi was started from a directory that contains multiple git repos. Run Pi from inside a single repo, or add `.engram/config.json` with `project_name` to the parent directory. | +| `🧠 repos · error` | A different tool or network error occurred. Expand the tool output in Pi for the full error message. | + Full tool details remain available by expanding the tool output in Pi. If `gentle-engram` or the Engram server is not installed/running, the compact tool reports an error instead of implying memory is available. ## What Pi can remember @@ -231,6 +238,7 @@ MCP tool calls still use Engram core's canonical project resolver at call time. | Existing MCP config was not replaced | Run `pi-engram init --force`. | | `mem_current_project` reports `/project/current` unsupported | Restart or upgrade the running `engram serve`; check `ENGRAM_URL`/`ENGRAM_BIN`. If `.engram/config.json` exists, Pi uses it as a temporary fallback. | | `mem_session_summary` cannot detect a project | Ask the user which project should receive the summary, then retry `mem_session_summary` with `project: "name"`. | +| Status bar shows `🧠 repos · ambiguous project` | Pi was started from a parent directory that contains multiple git repos. Run Pi from inside a single repo, or add `.engram/config.json` with `"project_name": "my-project"` to the ambiguous directory. | ## Next steps diff --git a/plugin/pi/index.ts b/plugin/pi/index.ts index 608edec4..25d7b313 100644 --- a/plugin/pi/index.ts +++ b/plugin/pi/index.ts @@ -261,6 +261,11 @@ function truncate(str: string, max: number): string { return str.length > max ? `${str.slice(0, max)}...` : str; } +function errorStatusLabel(message: string): string { + if (/ambiguous project/i.test(message)) return "ambiguous project"; + return "error"; +} + function stripPrivateTags(str: string): string { return redactPrivateTags(str).trim(); } @@ -686,7 +691,7 @@ async function executeMemoryTool(toolName: string, params: Record { assert.match(source, /error\.status === 404[\s\S]*detectLocalConfigProject\(cwd\) \|\| projectCurrentUnsupportedError\(cwd\)/); assert.match(source, /does not support \/project\/current/); }); + +test("ambiguous_project error maps to actionable status label, not generic 'error'", () => { + // The status bar must NOT show the generic 'error' label for ambiguous project conditions. + // Instead it should show an actionable label such as 'ambiguous project'. + assert.match(source, /function errorStatusLabel\(/); + // Verify the function maps ambiguous project messages to the actionable label + assert.match(source, /ambiguous project/); + // Verify executeMemoryTool uses errorStatusLabel instead of the bare 'error' string + assert.match(source, /errorStatusLabel\(message\)/); + // The bare '· error' hardcoded string should no longer be present in the catch block + assert.doesNotMatch(source, /setStatus\?\.\("engram",\s*`🧠 \$\{project\} · error`\)/); +});