chore: auto-commit before switching to gsd/M002/S01

This commit is contained in:
Lex Christopherson 2026-03-12 14:01:10 -06:00
parent 4e92a49d45
commit 9200401e55
9 changed files with 26 additions and 7 deletions

@ -1 +0,0 @@
Subproject commit afcbdfa956c83b3bb6f5476bb02437d9edeeda10

@ -1 +0,0 @@
Subproject commit 00d9aed6b03298b902452da0a29d9a8ff7f7f7c7

@ -1 +0,0 @@
Subproject commit 5f7e040254970b356e4e70d9d1a307fe07e2209a

View file

@ -56,7 +56,7 @@ import {
} from "./metrics.js";
import { join } from "node:path";
import { readdirSync, readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
import { execSync } from "node:child_process";
import { execSync, execFileSync } from "node:child_process";
import {
autoCommitCurrentBranch,
ensureSliceBranch,
@ -373,7 +373,8 @@ export async function startAuto(
try {
execSync("git rev-parse --git-dir", { cwd: base, stdio: "pipe" });
} catch {
execSync("git init", { cwd: base, stdio: "pipe" });
const mainBranch = loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
execFileSync("git", ["init", "-b", mainBranch], { cwd: base, stdio: "pipe" });
}
// Ensure .gitignore has baseline patterns

View file

@ -47,6 +47,7 @@ Full documentation for `~/.gsd/preferences.md` (global) and `.gsd/preferences.md
- `snapshots`: boolean — create snapshot commits (WIP saves) during long-running tasks. Default: `false`.
- `pre_merge_check`: boolean or `"auto"` — run pre-merge checks before merging a slice branch. `true` always runs, `false` never runs, `"auto"` runs when CI is detected. Default: `false`.
- `commit_type`: string — override the conventional commit type prefix. Must be one of: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `ci`, `build`, `style`. Default: inferred from diff content.
- `main_branch`: string — the primary branch name for new git repos (e.g., `"main"`, `"master"`, `"trunk"`). Also used by `getMainBranch()` as the preferred branch when auto-detection is ambiguous. Default: `"main"`.
---

View file

@ -27,8 +27,11 @@ export interface GitPreferences {
snapshots?: boolean;
pre_merge_check?: boolean | string;
commit_type?: string;
main_branch?: string;
}
export const VALID_BRANCH_NAME = /^[a-zA-Z0-9_\-\/.]+$/;
export interface CommitOptions {
message: string;
allowEmpty?: boolean;
@ -192,6 +195,12 @@ export class GitServiceImpl {
return this.git(["branch", "--show-current"]);
}
// Explicit preference takes priority over auto-detection
const configured = this.prefs.main_branch;
if (configured && VALID_BRANCH_NAME.test(configured)) {
return configured;
}
const symbolic = this.git(["symbolic-ref", "refs/remotes/origin/HEAD"], { allowFailure: true });
if (symbolic) {
const match = symbolic.match(/refs\/remotes\/origin\/(.+)$/);

View file

@ -145,6 +145,7 @@ See \`~/.gsd/agent/extensions/gsd/docs/preferences-reference.md\` for full field
- \`models\`: Model preferences for specific task types
- \`skill_discovery\`: Automatic skill detection preferences
- \`auto_supervisor\`: Supervision and gating rules for autonomous modes
- \`git\`: Git preferences — \`main_branch\` (default branch name for new repos, e.g., "main", "master", "trunk"), \`auto_push\`, \`snapshots\`, etc.
## Examples

View file

@ -20,8 +20,9 @@ import {
} from "./paths.js";
import { join } from "node:path";
import { readFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
import { execSync } from "node:child_process";
import { execSync, execFileSync } from "node:child_process";
import { ensureGitignore, ensurePreferences } from "./gitignore.js";
import { loadEffectiveGSDPreferences } from "./preferences.js";
// ─── Auto-start after discuss ─────────────────────────────────────────────────
@ -444,7 +445,8 @@ export async function showSmartEntry(
try {
execSync("git rev-parse --git-dir", { cwd: basePath, stdio: "pipe" });
} catch {
execSync("git init", { cwd: basePath, stdio: "pipe" });
const mainBranch = loadEffectiveGSDPreferences()?.preferences?.git?.main_branch || "main";
execFileSync("git", ["init", "-b", mainBranch], { cwd: basePath, stdio: "pipe" });
}
// ── Ensure .gitignore has baseline patterns ──────────────────────────

View file

@ -3,6 +3,7 @@ import { homedir } from "node:os";
import { isAbsolute, join } from "node:path";
import { getAgentDir } from "@mariozechner/pi-coding-agent";
import type { GitPreferences } from "./git-service.ts";
import { VALID_BRANCH_NAME } from "./git-service.ts";
const GLOBAL_PREFERENCES_PATH = join(homedir(), ".gsd", "preferences.md");
const LEGACY_GLOBAL_PREFERENCES_PATH = join(homedir(), ".pi", "agent", "gsd-preferences.md");
@ -639,6 +640,13 @@ function validatePreferences(preferences: GSDPreferences): {
errors.push(`git.commit_type must be one of: feat, fix, refactor, docs, test, chore, perf, ci, build, style`);
}
}
if (g.main_branch !== undefined) {
if (typeof g.main_branch === "string" && g.main_branch.trim() !== "" && VALID_BRANCH_NAME.test(g.main_branch)) {
git.main_branch = g.main_branch;
} else {
errors.push("git.main_branch must be a valid branch name (alphanumeric, _, -, /, .)");
}
}
if (Object.keys(git).length > 0) {
validated.git = git as GitPreferences;