@@ -400,6 +400,11 @@ export class InitCommand {
400400
401401 this . renderBanner ( extendMode ) ;
402402
403+ // Read existing config before language selection to detect language changes
404+ const existingConfigBeforeLanguageChange = extendMode
405+ ? await this . readConfigFile ( openspecPath )
406+ : null ;
407+
403408 // Get language configuration first (before AI tool selection)
404409 const selectedLanguage = await this . getSelectedLanguage ( openspecPath , extendMode ) ;
405410
@@ -447,7 +452,7 @@ export class InitCommand {
447452 )
448453 ) ;
449454 await this . createDirectoryStructure ( openspecPath ) ;
450- await this . ensureTemplateFiles ( openspecPath , config ) ;
455+ await this . ensureTemplateFiles ( openspecPath , config , existingConfigBeforeLanguageChange ) ;
451456 }
452457
453458 // Step 2: Configure AI tools
@@ -505,27 +510,23 @@ export class InitCommand {
505510 openspecPath : string ,
506511 extendMode : boolean
507512 ) : Promise < string > {
508- // Try to read existing config first
513+ // Non-interactive mode - check for --language flag first
514+ const nonInteractiveLanguage = this . resolveLanguageArg ( ) ;
515+ if ( nonInteractiveLanguage !== null ) {
516+ return nonInteractiveLanguage ;
517+ }
518+
519+ // Try to read existing config for default value
520+ let defaultLanguage = DEFAULT_LANGUAGE ;
509521 if ( extendMode ) {
510522 const existingConfig = await this . readConfigFile ( openspecPath ) ;
511523 if ( existingConfig ?. language ) {
512- // In extend mode, use existing language unless explicitly changed
513- const nonInteractiveLanguage = this . resolveLanguageArg ( ) ;
514- if ( nonInteractiveLanguage !== null ) {
515- return nonInteractiveLanguage ;
516- }
517- return existingConfig . language ;
524+ defaultLanguage = existingConfig . language ;
518525 }
519526 }
520527
521- // Non-interactive mode
522- const nonInteractiveLanguage = this . resolveLanguageArg ( ) ;
523- if ( nonInteractiveLanguage !== null ) {
524- return nonInteractiveLanguage ;
525- }
526-
527- // Interactive mode - prompt for language
528- return this . promptForLanguage ( ) ;
528+ // Interactive mode - prompt for language with default
529+ return this . promptForLanguage ( defaultLanguage ) ;
529530 }
530531
531532 private resolveLanguageArg ( ) : string | null {
@@ -555,7 +556,7 @@ export class InitCommand {
555556 return language . code ;
556557 }
557558
558- private async promptForLanguage ( ) : Promise < string > {
559+ private async promptForLanguage ( defaultLanguage : string = DEFAULT_LANGUAGE ) : Promise < string > {
559560 const { select } = await import ( '@inquirer/prompts' ) ;
560561
561562 const language = await select ( {
@@ -564,18 +565,23 @@ export class InitCommand {
564565 name : `${ lang . nativeName } (${ lang . code } )` ,
565566 value : lang . code ,
566567 } ) ) ,
567- default : DEFAULT_LANGUAGE ,
568+ default : defaultLanguage ,
568569 } ) ;
569570
570571 return language ;
571572 }
572573
573- private async readConfigFile ( openspecPath : string ) : Promise < { language ?: string } | null > {
574+ private async readConfigFile (
575+ openspecPath : string
576+ ) : Promise < Partial < OpenSpecConfig > | null > {
574577 const configPath = path . join ( openspecPath , CONFIG_FILE_NAME ) ;
575- return await FileSystemUtils . readJsonFile < { language ?: string } > ( configPath ) ;
578+ return await FileSystemUtils . readJsonFile < Partial < OpenSpecConfig > > ( configPath ) ;
576579 }
577580
578- private async saveConfigFile ( openspecPath : string , config : { language ?: string } ) : Promise < void > {
581+ private async saveConfigFile (
582+ openspecPath : string ,
583+ config : Partial < OpenSpecConfig >
584+ ) : Promise < void > {
579585 const configPath = path . join ( openspecPath , CONFIG_FILE_NAME ) ;
580586 const existingConfig = await this . readConfigFile ( openspecPath ) || { } ;
581587 const mergedConfig = { ...existingConfig , ...config } ;
@@ -829,9 +835,19 @@ export class InitCommand {
829835
830836 private async ensureTemplateFiles (
831837 openspecPath : string ,
832- config : OpenSpecConfig
838+ config : OpenSpecConfig ,
839+ previousConfig : Partial < OpenSpecConfig > | null = null
833840 ) : Promise < void > {
834- await this . writeTemplateFiles ( openspecPath , config , true ) ;
841+ // Check if language has changed - if so, regenerate templates
842+ // Use previousConfig if provided (read before language was saved), otherwise read from file
843+ const existingConfig =
844+ previousConfig || ( await this . readConfigFile ( openspecPath ) ) ;
845+ const languageChanged = existingConfig ?. language &&
846+ existingConfig . language !== config . language ;
847+
848+ // If language changed, force regeneration (skipExisting = false)
849+ // Otherwise, skip existing files to preserve user modifications
850+ await this . writeTemplateFiles ( openspecPath , config , ! languageChanged ) ;
835851 }
836852
837853 private async writeTemplateFiles (
@@ -1074,3 +1090,4 @@ export class InitCommand {
10741090 } ) . start ( ) ;
10751091 }
10761092}
1093+
0 commit comments