Commit 478ebaa53d4b

Vincent Demeester <vincent@sbr.pm>
2026-02-19 16:43:59
feat(ai-storage): detect git remote for project metadata
Added git remote detection to both /save-session command and background summarizer, providing the AI with org/repo info to infer the Project field — especially important for git worktrees where cwd paths are opaque. Updated history-system.md templates to require **Project:** and **Directory:** fields, with explicit rules for worktree handling and review-tool filter compatibility.
1 parent 634b0d3
Changed files (4)
dots
config
claude
pi
agent
extensions
home
common
dots/config/claude/skills/CORE/history-system.md
@@ -78,6 +78,9 @@ Note: Tool-specific data (like tool-outputs JSONL) stays under tool config:
 
 **Date:** YYYY-MM-DD
 **Tool:** claude
+**Project:** org/repo or ~/path (REQUIRED — infer from cwd, git remote, or context)
+**Directory:** /path/to/working/directory
+**Host:** hostname
 
 ## Summary
 Brief description of what was accomplished.
@@ -93,12 +96,20 @@ Brief description of what was accomplished.
 Result of the session.
 ```
 
+**IMPORTANT metadata rules:**
+- `**Project:**` is REQUIRED — use org/repo format (e.g., `tektoncd/pipeline`) or path (e.g., `~/src/home`)
+- `**Directory:**` is REQUIRED — the actual working directory (`process.cwd()`)
+- For git worktrees, **Project** must be the real project name, not the worktree path
+- `**Repository:**` can be used as alias for Project
+- These fields enable filtering in `review-tool` (`-d` / `-D` flags)
+
 ### Learning Entry
 ```markdown
 # Learning: <Description>
 
 **Date:** YYYY-MM-DD
 **Tool:** claude
+**Project:** org/repo or ~/path (when applicable)
 **Context:** What problem was being solved
 
 ## The Problem
@@ -121,6 +132,7 @@ How to avoid this in the future.
 
 **Date:** YYYY-MM-DD
 **Tool:** claude
+**Project:** org/repo or ~/path (when applicable)
 **Question:** What was being investigated
 
 ## Findings
@@ -140,6 +152,7 @@ What was learned and decided.
 
 **Date:** YYYY-MM-DD
 **Tool:** claude
+**Project:** org/repo or ~/path (when applicable)
 **Context:** Why this decision needed to be made
 
 ## Options Considered
@@ -159,6 +172,7 @@ What this means for the system.
 
 **Date:** YYYY-MM-DD
 **Tool:** claude
+**Project:** org/repo or ~/path (when applicable)
 **Context:** What was being built or executed
 
 ## What Was Done
dots/pi/agent/extensions/ai-storage/index.ts
@@ -833,6 +833,19 @@ export default function (pi: ExtensionAPI) {
 
 			const cwd = process.cwd();
 
+			// Try to detect git remote for project identification
+			let gitRemote = "";
+			try {
+				const { execSync } = await import("node:child_process");
+				gitRemote = execSync("git remote get-url origin 2>/dev/null", {
+					encoding: "utf-8",
+					cwd,
+					timeout: 3000,
+				}).trim();
+			} catch {
+				// Not a git repo or no remote
+			}
+
 			// Build the prompt for the AI
 			const prompt = `Please generate ${currentSessionFile ? "an updated" : "a"} session summary for this conversation.
 
@@ -854,9 +867,11 @@ The summary should include:
 - The outcome
 - Any next steps
 
-IMPORTANT: The metadata header MUST include **Project:** and/or **Repository:** when applicable.
-Infer the project name from the working directory, git remote, or conversation context.
-For example: "tektoncd/pipeline", "~/src/home", "vdemeester/chisel", etc.
+IMPORTANT: The metadata header MUST include **Project:** — this is REQUIRED for filtering.
+${gitRemote ? `Git remote: ${gitRemote}` : ""}
+Infer the project name as org/repo (e.g. "tektoncd/pipeline", "vdemeester/chisel") from the git remote, working directory, or conversation context.
+If working in a git worktree, use the real project name, NOT the worktree path.
+If no project can be inferred, use the working directory path (e.g. "~/src/home").
 
 Use this template format:
 
@@ -867,7 +882,7 @@ Use this template format:
 **Time:** ${time}
 **Host:** ${host}
 **Tool:** ${tool}
-**Project:** <infer from context, e.g. org/repo or ~/path>
+**Project:** <REQUIRED: org/repo or ~/path>
 **Directory:** ${cwd}
 
 ## Summary
dots/pi/agent/extensions/ai-storage/summarizer.ts
@@ -55,6 +55,17 @@ function summarizeWithPi(transcript: Transcript): string | null {
 		.map((m) => `${m.role.toUpperCase()}: ${m.content.slice(0, 2000)}`) // Truncate long messages
 		.join("\n\n---\n\n");
 
+	// Try to detect git remote from the working directory
+	let gitRemote = "";
+	try {
+		gitRemote = execSync(`git -C "${transcript.cwd}" remote get-url origin 2>/dev/null`, {
+			encoding: "utf-8",
+			timeout: 3000,
+		}).trim();
+	} catch {
+		// Not a git repo or no remote
+	}
+
 	const prompt = `Based on this AI coding session, generate a brief, descriptive title of 3-5 words.
 Then, create a structured markdown summary.
 
@@ -64,13 +75,14 @@ Session metadata:
 - Host: ${transcript.host}
 - Tool: ${transcript.tool}
 - Working directory: ${transcript.cwd}
+${gitRemote ? `- Git remote: ${gitRemote}` : ""}
 
 Conversation:
 ${conversationText}
 
-IMPORTANT: The metadata header MUST include **Project:** and/or **Repository:** when applicable.
-Infer the project name from the working directory, git remote, or conversation context.
-For example: "tektoncd/pipeline", "~/src/home", "vdemeester/chisel", etc.
+IMPORTANT: The metadata header MUST include **Project:** — this is REQUIRED.
+Infer the project name as org/repo (e.g. "tektoncd/pipeline", "vdemeester/chisel") from the git remote, working directory, or conversation context.
+If working in a git worktree, use the real project name, NOT the worktree path.
 
 Output ONLY the markdown, with this exact format:
 
@@ -80,7 +92,7 @@ Output ONLY the markdown, with this exact format:
 **Time:** ${transcript.savedAt.split("T")[1]?.slice(0, 5) || "unknown"}
 **Host:** ${transcript.host}
 **Tool:** ${transcript.tool}
-**Project:** <infer from working directory and conversation context>
+**Project:** <REQUIRED: org/repo or ~/path>
 **Directory:** ${transcript.cwd}
 
 ## Summary
home/common/dev/emacs.nix
@@ -104,6 +104,7 @@ let
       mcp
       minions
       modus-themes
+      doom-themes
       multi-vterm
       mu4e
       mwim