refactor: optimize feature loading in pipeline resume

Reduce redundant file reads by loading the feature object once and passing
it down the call chain instead of reloading it multiple times.

Changes:
- Pass feature object to resumePipelineFeature() instead of featureId
- Pass feature object to resumeFromPipelineStep() instead of featureId
- Remove redundant loadFeature() calls from these methods
- Add FeatureStatusWithPipeline import for type safety

This improves performance by eliminating unnecessary file I/O operations
and makes the data flow clearer.

Co-authored-by: gemini-code-assist bot

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Stephan Rieche
2026-01-02 12:42:04 +01:00
parent a9403651d4
commit c587947de6

View File

@@ -10,7 +10,13 @@
*/ */
import { ProviderFactory } from '../providers/provider-factory.js'; import { ProviderFactory } from '../providers/provider-factory.js';
import type { ExecuteOptions, Feature, PipelineConfig, PipelineStep } from '@automaker/types'; import type {
ExecuteOptions,
Feature,
FeatureStatusWithPipeline,
PipelineConfig,
PipelineStep,
} from '@automaker/types';
import { import {
buildPromptWithImages, buildPromptWithImages,
isAbortError, isAbortError,
@@ -710,12 +716,12 @@ Complete the pipeline step instructions above. Review the previous work and appl
const pipelineInfo = await this.detectPipelineStatus( const pipelineInfo = await this.detectPipelineStatus(
projectPath, projectPath,
featureId, featureId,
feature.status || '' (feature.status || '') as FeatureStatusWithPipeline
); );
if (pipelineInfo.isPipeline) { if (pipelineInfo.isPipeline) {
// Feature stuck in pipeline - use pipeline resume // Feature stuck in pipeline - use pipeline resume
return this.resumePipelineFeature(projectPath, featureId, useWorktrees, pipelineInfo); return this.resumePipelineFeature(projectPath, feature, useWorktrees, pipelineInfo);
} }
// Normal resume flow for non-pipeline features // Normal resume flow for non-pipeline features
@@ -746,11 +752,12 @@ Complete the pipeline step instructions above. Review the previous work and appl
/** /**
* Resume a feature that crashed during pipeline execution * Resume a feature that crashed during pipeline execution
* Handles edge cases: no context, missing step, deleted pipeline step * Handles edge cases: no context, missing step, deleted pipeline step
* @param feature - The feature object (already loaded to avoid redundant reads)
* @param pipelineInfo - Information about the pipeline status from detectPipelineStatus() * @param pipelineInfo - Information about the pipeline status from detectPipelineStatus()
*/ */
private async resumePipelineFeature( private async resumePipelineFeature(
projectPath: string, projectPath: string,
featureId: string, feature: Feature,
useWorktrees: boolean, useWorktrees: boolean,
pipelineInfo: { pipelineInfo: {
isPipeline: boolean; isPipeline: boolean;
@@ -761,6 +768,7 @@ Complete the pipeline step instructions above. Review the previous work and appl
config: PipelineConfig | null; config: PipelineConfig | null;
} }
): Promise<void> { ): Promise<void> {
const featureId = feature.id;
console.log( console.log(
`[AutoMode] Resuming feature ${featureId} from pipeline step ${pipelineInfo.stepId}` `[AutoMode] Resuming feature ${featureId} from pipeline step ${pipelineInfo.stepId}`
); );
@@ -798,8 +806,7 @@ Complete the pipeline step instructions above. Review the previous work and appl
`[AutoMode] Step ${pipelineInfo.stepId} no longer exists in pipeline, completing feature without pipeline` `[AutoMode] Step ${pipelineInfo.stepId} no longer exists in pipeline, completing feature without pipeline`
); );
const feature = await this.loadFeature(projectPath, featureId); const finalStatus = feature.skipTests ? 'waiting_approval' : 'verified';
const finalStatus = feature?.skipTests ? 'waiting_approval' : 'verified';
await this.updateFeatureStatus(projectPath, featureId, finalStatus); await this.updateFeatureStatus(projectPath, featureId, finalStatus);
@@ -824,7 +831,7 @@ Complete the pipeline step instructions above. Review the previous work and appl
return this.resumeFromPipelineStep( return this.resumeFromPipelineStep(
projectPath, projectPath,
featureId, feature,
useWorktrees, useWorktrees,
pipelineInfo.stepIndex, pipelineInfo.stepIndex,
pipelineInfo.config pipelineInfo.config
@@ -834,20 +841,17 @@ Complete the pipeline step instructions above. Review the previous work and appl
/** /**
* Resume pipeline execution from a specific step index * Resume pipeline execution from a specific step index
* Re-executes the step that crashed, then continues with remaining steps * Re-executes the step that crashed, then continues with remaining steps
* @param feature - The feature object (already loaded to avoid redundant reads)
* @param pipelineConfig - Pipeline config passed from detectPipelineStatus to avoid re-reading * @param pipelineConfig - Pipeline config passed from detectPipelineStatus to avoid re-reading
*/ */
private async resumeFromPipelineStep( private async resumeFromPipelineStep(
projectPath: string, projectPath: string,
featureId: string, feature: Feature,
useWorktrees: boolean, useWorktrees: boolean,
startFromStepIndex: number, startFromStepIndex: number,
pipelineConfig: PipelineConfig pipelineConfig: PipelineConfig
): Promise<void> { ): Promise<void> {
// Load feature and validate const featureId = feature.id;
const feature = await this.loadFeature(projectPath, featureId);
if (!feature) {
throw new Error(`Feature ${featureId} not found`);
}
const sortedSteps = [...pipelineConfig.steps].sort((a, b) => a.order - b.order); const sortedSteps = [...pipelineConfig.steps].sort((a, b) => a.order - b.order);
@@ -2763,7 +2767,7 @@ Review the previous work and continue the implementation. If the feature appears
private async detectPipelineStatus( private async detectPipelineStatus(
projectPath: string, projectPath: string,
featureId: string, featureId: string,
currentStatus: string currentStatus: FeatureStatusWithPipeline
): Promise<{ ): Promise<{
isPipeline: boolean; isPipeline: boolean;
stepId: string | null; stepId: string | null;