feat: Add settingsService integration for feature defaults and improve worktree handling

This commit is contained in:
gsxdsm
2026-03-02 03:28:37 -08:00
parent 34161ccc08
commit 33a2e04bf0
6 changed files with 105 additions and 32 deletions

View File

@@ -323,7 +323,7 @@ Your entire response should be valid JSON starting with { and ending with }. No
}
}
await parseAndCreateFeatures(projectPath, contentForParsing, events);
await parseAndCreateFeatures(projectPath, contentForParsing, events, settingsService);
logger.debug('========== generateFeaturesFromSpec() completed ==========');
}

View File

@@ -9,13 +9,16 @@ import { createLogger, atomicWriteJson, DEFAULT_BACKUP_COUNT } from '@automaker/
import { getFeaturesDir } from '@automaker/platform';
import { extractJsonWithArray } from '../../lib/json-extractor.js';
import { getNotificationService } from '../../services/notification-service.js';
import type { SettingsService } from '../../services/settings-service.js';
import { resolvePhaseModel } from '@automaker/model-resolver';
const logger = createLogger('SpecRegeneration');
export async function parseAndCreateFeatures(
projectPath: string,
content: string,
events: EventEmitter
events: EventEmitter,
settingsService?: SettingsService
): Promise<void> {
logger.info('========== parseAndCreateFeatures() started ==========');
logger.info(`Content length: ${content.length} chars`);
@@ -23,6 +26,37 @@ export async function parseAndCreateFeatures(
logger.info(content);
logger.info('========== END CONTENT ==========');
// Load default model and planning settings from settingsService
let defaultModel: string | undefined;
let defaultPlanningMode: string = 'skip';
let defaultRequirePlanApproval = false;
if (settingsService) {
try {
const globalSettings = await settingsService.getGlobalSettings();
const projectSettings = await settingsService.getProjectSettings(projectPath);
const defaultModelEntry =
projectSettings.defaultFeatureModel ?? globalSettings.defaultFeatureModel;
if (defaultModelEntry) {
const resolved = resolvePhaseModel(defaultModelEntry);
defaultModel = resolved.model;
}
defaultPlanningMode = globalSettings.defaultPlanningMode ?? 'skip';
defaultRequirePlanApproval = globalSettings.defaultRequirePlanApproval ?? false;
logger.info(
`[parseAndCreateFeatures] Using defaults: model=${defaultModel ?? 'none'}, planningMode=${defaultPlanningMode}, requirePlanApproval=${defaultRequirePlanApproval}`
);
} catch (settingsError) {
logger.warn(
'[parseAndCreateFeatures] Failed to load settings, using defaults:',
settingsError
);
}
}
try {
// Extract JSON from response using shared utility
logger.info('Extracting JSON from response using extractJsonWithArray...');
@@ -61,7 +95,7 @@ export async function parseAndCreateFeatures(
const featureDir = path.join(featuresDir, feature.id);
await secureFs.mkdir(featureDir, { recursive: true });
const featureData = {
const featureData: Record<string, unknown> = {
id: feature.id,
category: feature.category || 'Uncategorized',
title: feature.title,
@@ -70,12 +104,20 @@ export async function parseAndCreateFeatures(
priority: feature.priority || 2,
complexity: feature.complexity || 'moderate',
dependencies: feature.dependencies || [],
planningMode: 'skip',
requirePlanApproval: false,
planningMode: defaultPlanningMode,
requirePlanApproval:
defaultPlanningMode === 'skip' || defaultPlanningMode === 'lite'
? false
: defaultRequirePlanApproval,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
// Apply default model if available from settings
if (defaultModel) {
featureData.model = defaultModel;
}
// Use atomic write with backup support for crash protection
await atomicWriteJson(path.join(featureDir, 'feature.json'), featureData, {
backupCount: DEFAULT_BACKUP_COUNT,

View File

@@ -193,7 +193,11 @@ export class CodexModelCacheService {
* Infer tier from model ID
*/
private inferTier(modelId: string): 'premium' | 'standard' | 'basic' {
if (modelId.includes('max') || modelId.includes('gpt-5.2-codex')) {
if (
modelId.includes('max') ||
modelId.includes('gpt-5.2-codex') ||
modelId.includes('gpt-5.3-codex')
) {
return 'premium';
}
if (modelId.includes('mini')) {