refactor(06-02): migrate Batch 2 state change routes to facade pattern

- stop-feature.ts: Add facade parameter for feature stopping
- stop.ts: Add facadeFactory parameter for auto loop control
- verify-feature.ts: Add facadeFactory parameter for verification
- commit-feature.ts: Add facadeFactory parameter for committing

All routes maintain backward compatibility by accepting both
autoModeService (legacy) and facade/facadeFactory (new).
This commit is contained in:
Shirone
2026-01-30 21:33:11 +01:00
parent 8355eb7172
commit 0ee28c58df
4 changed files with 91 additions and 5 deletions

View File

@@ -4,9 +4,17 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { getErrorMessage, logError } from '../common.js';
export function createCommitFeatureHandler(autoModeService: AutoModeService) {
/**
* Create commit feature handler with transition compatibility.
* Accepts either autoModeService (legacy) or facadeFactory (new).
*/
export function createCommitFeatureHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureId, worktreePath } = req.body as {
@@ -23,6 +31,15 @@ export function createCommitFeatureHandler(autoModeService: AutoModeService) {
return;
}
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
const commitHash = await facade.commitFeature(featureId, worktreePath);
res.json({ success: true, commitHash });
return;
}
// Legacy path: use autoModeService directly
const commitHash = await autoModeService.commitFeature(projectPath, featureId, worktreePath);
res.json({ success: true, commitHash });
} catch (error) {

View File

@@ -4,9 +4,18 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { getErrorMessage, logError } from '../common.js';
export function createStopFeatureHandler(autoModeService: AutoModeService) {
/**
* Create stop feature handler with transition compatibility.
* Accepts either autoModeService (legacy) or facade (new).
* Note: stopFeature is feature-scoped (not project-scoped), so a single facade can be used.
*/
export function createStopFeatureHandler(
autoModeService: AutoModeService,
facade?: AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { featureId } = req.body as { featureId: string };
@@ -16,7 +25,10 @@ export function createStopFeatureHandler(autoModeService: AutoModeService) {
return;
}
const stopped = await autoModeService.stopFeature(featureId);
// Use facade if provided, otherwise fall back to autoModeService
const stopped = facade
? await facade.stopFeature(featureId)
: await autoModeService.stopFeature(featureId);
res.json({ success: true, stopped });
} catch (error) {
logError(error, 'Stop feature failed');

View File

@@ -4,12 +4,20 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { createLogger } from '@automaker/utils';
import { getErrorMessage, logError } from '../common.js';
const logger = createLogger('AutoMode');
export function createStopHandler(autoModeService: AutoModeService) {
/**
* Create stop handler with transition compatibility.
* Accepts either autoModeService (legacy) or facadeFactory (new).
*/
export function createStopHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, branchName } = req.body as {
@@ -31,6 +39,38 @@ export function createStopHandler(autoModeService: AutoModeService) {
? `worktree ${normalizedBranchName}`
: 'main worktree';
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
// Check if running
if (!facade.isAutoLoopRunning(normalizedBranchName)) {
res.json({
success: true,
message: `Auto mode is not running for ${worktreeDesc}`,
wasRunning: false,
branchName: normalizedBranchName,
});
return;
}
// Stop the auto loop for this project/worktree
const runningCount = await facade.stopAutoLoop(normalizedBranchName);
logger.info(
`Stopped auto loop for ${worktreeDesc} in project: ${projectPath}, ${runningCount} features still running`
);
res.json({
success: true,
message: 'Auto mode stopped',
runningFeaturesCount: runningCount,
branchName: normalizedBranchName,
});
return;
}
// Legacy path: use autoModeService directly
// Check if running
if (!autoModeService.isAutoLoopRunningForProject(projectPath, normalizedBranchName)) {
res.json({

View File

@@ -4,9 +4,17 @@
import type { Request, Response } from 'express';
import type { AutoModeService } from '../../../services/auto-mode-service.js';
import type { AutoModeServiceFacade } from '../../../services/auto-mode/index.js';
import { getErrorMessage, logError } from '../common.js';
export function createVerifyFeatureHandler(autoModeService: AutoModeService) {
/**
* Create verify feature handler with transition compatibility.
* Accepts either autoModeService (legacy) or facadeFactory (new).
*/
export function createVerifyFeatureHandler(
autoModeService: AutoModeService,
facadeFactory?: (projectPath: string) => AutoModeServiceFacade
) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureId } = req.body as {
@@ -22,6 +30,15 @@ export function createVerifyFeatureHandler(autoModeService: AutoModeService) {
return;
}
// Use facade if factory is provided, otherwise fall back to autoModeService
if (facadeFactory) {
const facade = facadeFactory(projectPath);
const passes = await facade.verifyFeature(featureId);
res.json({ success: true, passes });
return;
}
// Legacy path: use autoModeService directly
const passes = await autoModeService.verifyFeature(projectPath, featureId);
res.json({ success: true, passes });
} catch (error) {