From 5cb91829115150229412cc2797fff292664b3e4f Mon Sep 17 00:00:00 2001 From: le king fu Date: Sun, 4 Oct 2026 09:11:46 -0400 Subject: [PATCH] fix(agent): collapse doubled slashes in cwd before project mapping Resolves #49 Co-Authored-By: Claude Opus 5.5 --- __tests__/agent-claude-usage.test.js | 3 +++ agent/claude-usage/aggregate.js | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/__tests__/agent-claude-usage.test.js b/__tests__/agent-claude-usage.test.js index 636c912..4452043 100644 --- a/__tests__/agent-claude-usage.test.js +++ b/__tests__/agent-claude-usage.test.js @@ -171,6 +171,9 @@ describe("mapProject", () => { expect( mapProject(`${HOME}/claude-code/vps-health-api/.claude/worktrees/agent-x`, HOME), ).toBe("vps-health-api"); + // A doubled slash never yields an empty project name. + expect(mapProject(`${HOME}/claude-code//simpl-liste/app`, HOME)).toBe("simpl-liste"); + expect(mapProject(`${HOME}//claude-code`, HOME)).toBe("(monorepo)"); }); it("rule 1: .spikes and .archive keep their second segment", () => { diff --git a/agent/claude-usage/aggregate.js b/agent/claude-usage/aggregate.js index 7423e23..c5f358b 100644 --- a/agent/claude-usage/aggregate.js +++ b/agent/claude-usage/aggregate.js @@ -89,8 +89,11 @@ function escapeRe(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } +// Collapses repeated slashes and drops trailing ones, so "/claude-code//x" +// cannot yield an empty project name. function stripTrailingSlashes(p) { - return p.length > 1 ? p.replace(/\/+$/, "") : p; + const collapsed = p.replace(/\/{2,}/g, "/"); + return collapsed.length > 1 ? collapsed.replace(/\/+$/, "") : collapsed; } // Project name from a transcript line's `cwd`, rules applied in order: