diff --git a/pi-coding-extension.ts b/pi-coding-extension.ts index 34cd4dd..ac411d1 100644 --- a/pi-coding-extension.ts +++ b/pi-coding-extension.ts @@ -897,6 +897,47 @@ async function runVersionBump(pi: ExtensionAPI, ctx: ExtensionCommandContext): P ctx.ui.notify(`Version ${newTag} getaggt.`, "info"); } +// Stellt sicher, dass ctx.cwd ein eigenes git-Repo hat (nicht nur ein übergeordnetes). +// Hintergrund: git add -A sucht das Repo-Root — bei Home-Verzeichnis-Repos würde das den +// gesamten Home-Baum indizieren (HuggingFace-Modelle, Podman-Overlays usw., 100k+ Dateien). +// Wird am Anfang aller Coding-Kommandos aufgerufen die git-Commits durchführen. +async function ensureLocalGitRepo( + pi: ExtensionAPI, + ctx: ExtensionCommandContext +): Promise { + const localGit = await pi.exec("bash", ["-c", "test -d .git && echo yes"], { cwd: ctx.cwd }); + if (localGit.stdout.trim() === "yes") return; + + const root = await pi.exec("bash", ["-c", "git rev-parse --show-toplevel 2>/dev/null"], { cwd: ctx.cwd }); + const repoRoot = root.stdout.trim(); + if (repoRoot && repoRoot !== ctx.cwd) { + ctx.ui.notify( + `⚠ Kein lokales Git-Repo in ${ctx.cwd} (Git-Root war: ${repoRoot}) — git init wird ausgeführt.`, + "warning" + ); + } + + await pi.exec("bash", ["-c", "git init"], { cwd: ctx.cwd }); + + const gitignoreCheck = await pi.exec("bash", ["-c", "test -f .gitignore && echo exists"], { cwd: ctx.cwd }); + if (gitignoreCheck.stdout.trim() !== "exists") { + const gitignore = [ + "__pycache__/", "*.pyc", "*.pyo", ".venv/", "venv/", + "target/", "*.o", "*.d", + "node_modules/", "dist/", "build/", "*.egg-info/", + ".env", ".DS_Store", "*.swp", + ].join("\n") + "\n"; + await pi.exec("bash", ["-c", 'printf "%s" "$1" > .gitignore', "_", gitignore], { cwd: ctx.cwd }); + } + + await pi.exec( + "bash", + ["-c", "git add . && git commit -m 'chore: init project' || true"], + { cwd: ctx.cwd } + ); + ctx.ui.notify(`Git-Repo initialisiert: ${ctx.cwd}`, "info"); +} + // Committed alle ungespeicherten Änderungen nach SHIP — Sicherheitsnetz falls der LLM es vergessen hat. async function autoCommitIfDirty(pi: ExtensionAPI, ctx: ExtensionCommandContext): Promise { const status = await pi.exec("bash", ["-c", "git status --porcelain"], { cwd: ctx.cwd }); @@ -1098,6 +1139,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-coding-server.sh ausführen", "error"); return; } + await ensureLocalGitRepo(pi, ctx); await writeTaskMd(pi, ctx, task); await selectRole(pi, ctx, "coder"); currentActivity = "Coder implementiert…"; @@ -1127,6 +1169,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-coding-server.sh ausführen", "error"); return; } + await ensureLocalGitRepo(pi, ctx); await selectRole(pi, ctx, "coder"); currentActivity = "Coder fixt Judge-Kritik…"; await sendAndWait(pi, ctx, fixPrompt(args || "")); @@ -1191,6 +1234,8 @@ export default function (pi: ExtensionAPI) { } try { + await ensureLocalGitRepo(pi, ctx); + if (continueMode) { // --continue: Implementierungsphase überspringen, direkt in Judge→Fix-Schleife // Erweiterter Auftrag wird als Zusatzauftrag in TASK.md eingetragen (falls angegeben) @@ -1437,6 +1482,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-coding-server.sh ausführen", "error"); return; } + await ensureLocalGitRepo(pi, ctx); await selectRole(pi, ctx, "coder"); currentActivity = "Coder patcht…"; await sendAndWait(pi, ctx, patchPrompt(change));