refactor(auto-mode): enhance feature retrieval logic in facade and global service

- Replaced synchronous feature retrieval with asynchronous logic in both AutoModeServiceFacade and GlobalAutoModeService.
- Updated filtering logic to resolve the primary branch name for main worktrees, improving accuracy in feature status checks.
- This change enhances the responsiveness and correctness of feature handling in auto mode operations.
This commit is contained in:
gsxdsm
2026-02-14 21:28:15 -08:00
parent 0745832d1e
commit 8542a32f4f
2 changed files with 32 additions and 33 deletions

View File

@@ -48,15 +48,6 @@ import type {
const execAsync = promisify(exec); const execAsync = promisify(exec);
const logger = createLogger('AutoModeServiceFacade'); const logger = createLogger('AutoModeServiceFacade');
/**
* Generate a unique key for worktree-scoped auto loop state
* (mirrors the function in AutoModeService for status lookups)
*/
function getWorktreeAutoLoopKey(projectPath: string, branchName: string | null): string {
const normalizedBranch = branchName === 'main' ? null : branchName;
return `${projectPath}::${normalizedBranch ?? '__main__'}`;
}
/** /**
* AutoModeServiceFacade provides a clean interface for auto-mode functionality. * AutoModeServiceFacade provides a clean interface for auto-mode functionality.
* *
@@ -240,18 +231,22 @@ export class AutoModeServiceFacade {
// Callbacks // Callbacks
(pPath, featureId, useWorktrees, isAutoMode) => (pPath, featureId, useWorktrees, isAutoMode) =>
facadeInstance!.executeFeature(featureId, useWorktrees, isAutoMode), facadeInstance!.executeFeature(featureId, useWorktrees, isAutoMode),
(pPath, branchName) => async (pPath, branchName) => {
featureLoader const features = await featureLoader.getAll(pPath);
.getAll(pPath) // For main worktree (branchName === null), resolve the actual primary branch name
.then((features) => // so features with branchName matching the primary branch are included
features.filter( let primaryBranch: string | null = null;
(f) => if (branchName === null) {
(f.status === 'backlog' || f.status === 'ready') && primaryBranch = await worktreeResolver.getCurrentBranch(pPath);
(branchName === null }
? !f.branchName || f.branchName === 'main' return features.filter(
: f.branchName === branchName) (f) =>
) (f.status === 'backlog' || f.status === 'ready') &&
), (branchName === null
? !f.branchName || (primaryBranch && f.branchName === primaryBranch)
: f.branchName === branchName)
);
},
(pPath, branchName, maxConcurrency) => (pPath, branchName, maxConcurrency) =>
facadeInstance!.saveExecutionStateForProject(branchName, maxConcurrency), facadeInstance!.saveExecutionStateForProject(branchName, maxConcurrency),
(pPath, branchName) => facadeInstance!.clearExecutionState(branchName), (pPath, branchName) => facadeInstance!.clearExecutionState(branchName),

View File

@@ -66,18 +66,22 @@ export class GlobalAutoModeService {
); );
}, },
// getBacklogFeaturesFn // getBacklogFeaturesFn
(pPath, branchName) => async (pPath, branchName) => {
featureLoader const features = await featureLoader.getAll(pPath);
.getAll(pPath) // For main worktree (branchName === null), resolve the actual primary branch name
.then((features) => // so features with branchName matching the primary branch are included
features.filter( let primaryBranch: string | null = null;
(f) => if (branchName === null) {
(f.status === 'backlog' || f.status === 'ready') && primaryBranch = await this.worktreeResolver.getCurrentBranch(pPath);
(branchName === null }
? !f.branchName || f.branchName === 'main' return features.filter(
: f.branchName === branchName) (f) =>
) (f.status === 'backlog' || f.status === 'ready') &&
), (branchName === null
? !f.branchName || (primaryBranch && f.branchName === primaryBranch)
: f.branchName === branchName)
);
},
// saveExecutionStateFn - placeholder // saveExecutionStateFn - placeholder
async () => {}, async () => {},
// clearExecutionStateFn - placeholder // clearExecutionStateFn - placeholder