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 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.
*
@@ -240,18 +231,22 @@ export class AutoModeServiceFacade {
// Callbacks
(pPath, featureId, useWorktrees, isAutoMode) =>
facadeInstance!.executeFeature(featureId, useWorktrees, isAutoMode),
(pPath, branchName) =>
featureLoader
.getAll(pPath)
.then((features) =>
features.filter(
(f) =>
(f.status === 'backlog' || f.status === 'ready') &&
(branchName === null
? !f.branchName || f.branchName === 'main'
: f.branchName === branchName)
)
),
async (pPath, branchName) => {
const features = await featureLoader.getAll(pPath);
// For main worktree (branchName === null), resolve the actual primary branch name
// so features with branchName matching the primary branch are included
let primaryBranch: string | null = null;
if (branchName === null) {
primaryBranch = await worktreeResolver.getCurrentBranch(pPath);
}
return features.filter(
(f) =>
(f.status === 'backlog' || f.status === 'ready') &&
(branchName === null
? !f.branchName || (primaryBranch && f.branchName === primaryBranch)
: f.branchName === branchName)
);
},
(pPath, branchName, maxConcurrency) =>
facadeInstance!.saveExecutionStateForProject(branchName, maxConcurrency),
(pPath, branchName) => facadeInstance!.clearExecutionState(branchName),

View File

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