fix(project-name): use parent/worktree composite so observations don't cross worktrees
Revert of #1820 behavior. Each worktree now gets its own bucket: - In a worktree, primary = `parent/worktree` (e.g. `claude-mem/dar-es-salaam`) - In a main repo, primary = basename (unchanged) - allProjects is always `[primary]` — strict isolation at query time Includes a one-off maintenance script (scripts/worktree-remap.ts) that retroactively reattributes past sessions to their worktree using path signals in observations and user prompts. Two-rule inference keeps the remap high-confidence: 1. The worktree basename in the path matches the session's current plain project name (pre-#1820 era; trusted). 2. Or all worktree path signals converge on a single (parent, worktree) across the session. Ambiguous sessions are skipped. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -58,21 +58,24 @@ export function getProjectName(cwd: string | null | undefined): string {
|
||||
* Project context with worktree awareness
|
||||
*/
|
||||
export interface ProjectContext {
|
||||
/** Canonical project name for writes/queries (parent repo in worktrees) */
|
||||
/** Canonical project name for writes/queries; `parent/worktree` when in a worktree */
|
||||
primary: string;
|
||||
/** Parent project name if in a worktree, null otherwise */
|
||||
parent: string | null;
|
||||
/** True if currently in a worktree */
|
||||
isWorktree: boolean;
|
||||
/** All projects to query: [primary] for main repo, [parentRepo, worktreeName] for worktree */
|
||||
/** Projects to query — always `[primary]` so observations don't cross worktrees */
|
||||
allProjects: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project context with worktree detection.
|
||||
*
|
||||
* When in a worktree, returns both the worktree project name and parent project name
|
||||
* for unified timeline queries.
|
||||
* Each worktree is its own bucket. When in a worktree, `primary` is the
|
||||
* composite `parent/worktree` (e.g. `claude-mem/dar-es-salaam`) so worktrees
|
||||
* are uniquely identified and grouped under their parent project without
|
||||
* mixing observations across them. In the main repo, `primary` is just the
|
||||
* project basename.
|
||||
*
|
||||
* @param cwd - Current working directory (absolute path)
|
||||
* @returns ProjectContext with worktree info
|
||||
@@ -88,14 +91,12 @@ export function getProjectContext(cwd: string | null | undefined): ProjectContex
|
||||
const worktreeInfo = detectWorktree(expandedCwd);
|
||||
|
||||
if (worktreeInfo.isWorktree && worktreeInfo.parentProjectName) {
|
||||
// In a worktree: use parent project name as primary so observations
|
||||
// are stored under the same project as the main repo (#1081, #1500, #1819)
|
||||
const allProjects = Array.from(new Set([worktreeInfo.parentProjectName, cwdProjectName]));
|
||||
const composite = `${worktreeInfo.parentProjectName}/${cwdProjectName}`;
|
||||
return {
|
||||
primary: worktreeInfo.parentProjectName,
|
||||
primary: composite,
|
||||
parent: worktreeInfo.parentProjectName,
|
||||
isWorktree: true,
|
||||
allProjects
|
||||
allProjects: [composite]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user