chore: remove dead code from branchless refactor (#510)
Remove methods, fields, and comments left over after the branchless worktree architecture landed: - git-service.ts: delete isOnSliceBranch, getActiveSliceBranch, branchExists (private), discardUntrackedRuntimeFiles (private); update writeIntegrationBranch comment and remove --force flag - worktree.ts: delete isOnSliceBranch, getActiveSliceBranch exports; update module doc from "branch-per-slice" to "worktree utilities" - state.ts: remove activeBranch computation (always null) - types.ts: remove GSDState.activeBranch field - templates/state.md: remove "Slice Branch" line - auto.ts, guided-flow.ts: update "branch-per-slice" comments - Tests updated to match Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e6d55f8aaf
commit
dda9d713f2
10 changed files with 20 additions and 109 deletions
|
|
@ -553,7 +553,7 @@ export async function startAuto(
|
|||
return;
|
||||
}
|
||||
|
||||
// Ensure git repo exists — GSD needs it for branch-per-slice
|
||||
// Ensure git repo exists — GSD needs it for worktree isolation
|
||||
try {
|
||||
execSync("git rev-parse --git-dir", { cwd: base, stdio: "pipe" });
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -132,13 +132,11 @@ export function readIntegrationBranch(basePath: string, milestoneId: string): st
|
|||
* Persist the integration branch for a milestone.
|
||||
*
|
||||
* Called when auto-mode starts on a milestone. Records the branch the user
|
||||
* was on at that point, so that slice branches merge back to it instead of
|
||||
* the repo's default branch. Idempotent when the branch matches; updates
|
||||
* the record when the user starts from a different branch.
|
||||
* was on at that point, so the milestone worktree merges back to the correct
|
||||
* branch. Idempotent when the branch matches; updates the record when the
|
||||
* user starts from a different branch.
|
||||
*
|
||||
* The file is committed immediately so it survives branch switches — the
|
||||
* pre-switch auto-commit excludes `.gsd/` to avoid merge conflicts, and
|
||||
* uncommitted `.gsd/` files are discarded during checkout.
|
||||
* The file is committed immediately so the metadata is persisted in git.
|
||||
*/
|
||||
export function writeIntegrationBranch(basePath: string, milestoneId: string, branch: string): void {
|
||||
// Don't record slice branches as the integration target
|
||||
|
|
@ -167,7 +165,7 @@ export function writeIntegrationBranch(basePath: string, milestoneId: string, br
|
|||
|
||||
// Commit immediately so the metadata is persisted in git.
|
||||
try {
|
||||
runGit(basePath, ["add", "--force", metaFile]);
|
||||
runGit(basePath, ["add", metaFile]);
|
||||
runGit(basePath, ["commit", "--no-verify", "-F", "-"], {
|
||||
input: `chore(${milestoneId}): record integration branch`,
|
||||
});
|
||||
|
|
@ -404,48 +402,8 @@ export class GitServiceImpl {
|
|||
}
|
||||
|
||||
/** True if currently on a GSD slice branch. */
|
||||
isOnSliceBranch(): boolean {
|
||||
const current = this.getCurrentBranch();
|
||||
return SLICE_BRANCH_RE.test(current);
|
||||
}
|
||||
|
||||
/** Returns the slice branch name if on one, null otherwise. */
|
||||
getActiveSliceBranch(): string | null {
|
||||
try {
|
||||
const current = this.getCurrentBranch();
|
||||
return SLICE_BRANCH_RE.test(current) ? current : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Branch Lifecycle ──────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Check if a local branch exists. Native libgit2 when available, execSync fallback.
|
||||
*/
|
||||
private branchExists(branch: string): boolean {
|
||||
return nativeBranchExists(this.basePath, branch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove untracked runtime files from the working tree.
|
||||
*
|
||||
* Complements `git checkout -- .gsd/` (which only handles tracked files).
|
||||
* Runtime files can end up untracked after a cleanup commit removes them
|
||||
* from the current branch's HEAD — but the target branch may still have
|
||||
* them committed. Without this step, `git checkout` fails with:
|
||||
* "The following untracked working tree files would be overwritten by checkout"
|
||||
*
|
||||
* `git clean -fdx` is safe here because:
|
||||
* - Only removes *untracked* files (tracked files are untouched)
|
||||
* - Targets only the specific runtime paths listed in RUNTIME_EXCLUSION_PATHS
|
||||
* - These files are always regenerated by GSD on the next run
|
||||
*/
|
||||
private discardUntrackedRuntimeFiles(): void {
|
||||
this.git(["clean", "-fdx", "--", ...RUNTIME_EXCLUSION_PATHS], { allowFailure: true });
|
||||
}
|
||||
|
||||
// ─── S05 Features ─────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ export async function showSmartEntry(
|
|||
): Promise<void> {
|
||||
const stepMode = options?.step;
|
||||
|
||||
// ── Ensure git repo exists — GSD needs it for branch-per-slice ──────
|
||||
// ── Ensure git repo exists — GSD needs it for worktree isolation ──────
|
||||
try {
|
||||
execSync("git rev-parse --git-dir", { cwd: basePath, stdio: "pipe" });
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import {
|
|||
resolveGsdRootFile,
|
||||
gsdRoot,
|
||||
} from './paths.js';
|
||||
import { getActiveSliceBranch } from './worktree.js';
|
||||
|
||||
import { milestoneIdSort, findMilestoneIds } from './guided-flow.js';
|
||||
import { nativeBatchParseGsdFiles, type BatchParsedFile } from './native-parser-bridge.js';
|
||||
|
||||
|
|
@ -438,8 +438,6 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
};
|
||||
}
|
||||
|
||||
const activeBranch = getActiveSliceBranch(basePath);
|
||||
|
||||
// Check if the slice has a plan
|
||||
const planFile = resolveSliceFile(basePath, activeMilestone.id, activeSlice.id, "PLAN");
|
||||
const slicePlanContent = planFile ? await cachedLoadFile(planFile) : null;
|
||||
|
|
@ -453,7 +451,7 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
recentDecisions: [],
|
||||
blockers: [],
|
||||
nextAction: `Plan slice ${activeSlice.id} (${activeSlice.title}).`,
|
||||
activeBranch: activeBranch ?? undefined,
|
||||
|
||||
registry,
|
||||
requirements,
|
||||
progress: {
|
||||
|
|
@ -480,7 +478,7 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
recentDecisions: [],
|
||||
blockers: [],
|
||||
nextAction: `All tasks done in ${activeSlice.id}. Write slice summary and complete slice.`,
|
||||
activeBranch: activeBranch ?? undefined,
|
||||
|
||||
registry,
|
||||
requirements,
|
||||
progress: {
|
||||
|
|
@ -501,7 +499,7 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
recentDecisions: [],
|
||||
blockers: [],
|
||||
nextAction: `Slice ${activeSlice.id} has a plan file but no tasks. Add tasks to the plan.`,
|
||||
activeBranch: activeBranch ?? undefined,
|
||||
|
||||
registry,
|
||||
requirements,
|
||||
progress: {
|
||||
|
|
@ -547,7 +545,7 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
recentDecisions: [],
|
||||
blockers: [`Task ${blockerTaskId} discovered a blocker requiring slice replan`],
|
||||
nextAction: `Task ${blockerTaskId} reported blocker_discovered. Replan slice ${activeSlice.id} before continuing.`,
|
||||
activeBranch: activeBranch ?? undefined,
|
||||
|
||||
activeWorkspace: undefined,
|
||||
registry,
|
||||
requirements,
|
||||
|
|
@ -578,7 +576,6 @@ async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
nextAction: hasInterrupted
|
||||
? `Resume interrupted work on ${activeTask.id}: ${activeTask.title} in slice ${activeSlice.id}. Read continue.md first.`
|
||||
: `Execute ${activeTask.id}: ${activeTask.title} in slice ${activeSlice.id}.`,
|
||||
activeBranch: activeBranch ?? undefined,
|
||||
registry,
|
||||
requirements,
|
||||
progress: {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
**Active Slice:** {{sliceId}}: {{sliceTitle}}
|
||||
**Active Task:** {{taskId}}: {{taskTitle}}
|
||||
**Phase:** {{phase}}
|
||||
**Slice Branch:** {{activeBranch}}
|
||||
**Active Workspace:** {{activeWorkspace}}
|
||||
**Next Action:** {{nextAction}}
|
||||
**Last Updated:** {{date}}
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ async function main(): Promise<void> {
|
|||
return dir;
|
||||
}
|
||||
|
||||
// ─── getCurrentBranch / isOnSliceBranch / getActiveSliceBranch ─────────
|
||||
// ─── getCurrentBranch ────────────────────────────────────────────────
|
||||
|
||||
console.log("\n=== Branch queries ===");
|
||||
|
||||
|
|
@ -541,21 +541,13 @@ async function main(): Promise<void> {
|
|||
const repo = initBranchTestRepo();
|
||||
const svc = new GitServiceImpl(repo);
|
||||
|
||||
// On main
|
||||
assertEq(svc.getCurrentBranch(), "main", "getCurrentBranch returns main on main branch");
|
||||
assertEq(svc.isOnSliceBranch(), false, "isOnSliceBranch returns false on main");
|
||||
assertEq(svc.getActiveSliceBranch(), null, "getActiveSliceBranch returns null on main");
|
||||
|
||||
// Create and checkout a slice branch manually
|
||||
run("git checkout -b gsd/M001/S01", repo);
|
||||
assertEq(svc.getCurrentBranch(), "gsd/M001/S01", "getCurrentBranch returns slice branch name");
|
||||
assertEq(svc.isOnSliceBranch(), true, "isOnSliceBranch returns true on slice branch");
|
||||
assertEq(svc.getActiveSliceBranch(), "gsd/M001/S01", "getActiveSliceBranch returns branch name on slice branch");
|
||||
|
||||
// Non-slice feature branch
|
||||
run("git checkout -b feature/foo", repo);
|
||||
assertEq(svc.isOnSliceBranch(), false, "isOnSliceBranch returns false on non-slice branch");
|
||||
assertEq(svc.getActiveSliceBranch(), null, "getActiveSliceBranch returns null on non-slice branch");
|
||||
assertEq(svc.getCurrentBranch(), "feature/foo", "getCurrentBranch returns feature branch name");
|
||||
|
||||
rmSync(repo, { recursive: true, force: true });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ import {
|
|||
getCurrentBranch,
|
||||
getMainBranch,
|
||||
getSliceBranchName,
|
||||
isOnSliceBranch,
|
||||
getActiveSliceBranch,
|
||||
autoCommitCurrentBranch,
|
||||
SLICE_BRANCH_RE,
|
||||
} from "../worktree.ts";
|
||||
|
||||
import { deriveState } from "../state.ts";
|
||||
|
|
@ -109,8 +108,7 @@ async function main(): Promise<void> {
|
|||
const sliceBranch = getSliceBranchName("M001", "S01", "alpha");
|
||||
run(`git checkout -b ${sliceBranch}`, wt.path);
|
||||
assertEq(getCurrentBranch(wt.path), "gsd/alpha/M001/S01", "worktree-namespaced slice branch");
|
||||
assertTrue(isOnSliceBranch(wt.path), "isOnSliceBranch returns true");
|
||||
assertEq(getActiveSliceBranch(wt.path), "gsd/alpha/M001/S01", "getActiveSliceBranch returns namespaced branch");
|
||||
assertTrue(SLICE_BRANCH_RE.test(getCurrentBranch(wt.path)), "slice branch regex matches namespaced branch");
|
||||
|
||||
// ── Do work on slice branch, then merge to worktree branch ─────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ import {
|
|||
autoCommitCurrentBranch,
|
||||
captureIntegrationBranch,
|
||||
detectWorktreeName,
|
||||
getActiveSliceBranch,
|
||||
getCurrentBranch,
|
||||
getMainBranch,
|
||||
getSliceBranchName,
|
||||
isOnSliceBranch,
|
||||
parseSliceBranch,
|
||||
setActiveMilestoneId,
|
||||
SLICE_BRANCH_RE,
|
||||
|
|
@ -37,12 +35,6 @@ run('git commit -m "chore: init"', base);
|
|||
|
||||
async function main(): Promise<void> {
|
||||
|
||||
console.log("\n=== getActiveSliceBranch on main ===");
|
||||
assertEq(getActiveSliceBranch(base), null, "getActiveSliceBranch returns null on main");
|
||||
|
||||
console.log("\n=== isOnSliceBranch on main ===");
|
||||
assertEq(isOnSliceBranch(base), false, "isOnSliceBranch returns false on main");
|
||||
|
||||
console.log("\n=== autoCommitCurrentBranch ===");
|
||||
// Clean — should return null
|
||||
const cleanResult = autoCommitCurrentBranch(base, "execute-task", "M001/S01/T01");
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@ export interface GSDState {
|
|||
recentDecisions: string[];
|
||||
blockers: string[];
|
||||
nextAction: string;
|
||||
activeBranch?: string;
|
||||
activeWorkspace?: string;
|
||||
registry: MilestoneRegistryEntry[];
|
||||
requirements?: RequirementCounts;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
/**
|
||||
* GSD Slice Branch Management — Thin Facade
|
||||
* GSD Worktree Utilities
|
||||
*
|
||||
* Simple branch-per-slice workflow. No worktrees, no registry.
|
||||
* Runtime state (metrics, activity, lock, STATE.md) is gitignored
|
||||
* so branch switches are clean.
|
||||
* Pure utility functions for worktree name detection, legacy branch name
|
||||
* parsing, and integration branch capture.
|
||||
*
|
||||
* All git-mutation functions delegate to GitServiceImpl from git-service.ts.
|
||||
* Pure utility functions (detectWorktreeName, getSliceBranchName, parseSliceBranch,
|
||||
* SLICE_BRANCH_RE) remain standalone.
|
||||
* SLICE_BRANCH_RE) remain standalone for backwards compatibility.
|
||||
*
|
||||
* Branchless architecture: all work commits sequentially on the milestone branch.
|
||||
* Pure utility functions (detectWorktreeName, getSliceBranchName, parseSliceBranch,
|
||||
|
|
@ -147,26 +145,4 @@ export function autoCommitCurrentBranch(
|
|||
return getService(basePath).autoCommit(unitType, unitId);
|
||||
}
|
||||
|
||||
// ─── Query Functions (delegate to GitServiceImpl) ──────────────────────────
|
||||
|
||||
/**
|
||||
* Check if we're currently on a slice branch (not main).
|
||||
* Handles both plain (gsd/M001/S01) and worktree-namespaced (gsd/wt/M001/S01) branches.
|
||||
*/
|
||||
export function isOnSliceBranch(basePath: string): boolean {
|
||||
const current = getCurrentBranch(basePath);
|
||||
return SLICE_BRANCH_RE.test(current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active slice branch name, or null if on main.
|
||||
* Handles both plain and worktree-namespaced branch patterns.
|
||||
*/
|
||||
export function getActiveSliceBranch(basePath: string): string | null {
|
||||
try {
|
||||
const current = getCurrentBranch(basePath);
|
||||
return SLICE_BRANCH_RE.test(current) ? current : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue