@@ -278,17 +278,32 @@ func generateAndWrite(client llm.Client, summary, conversation string) error {
278278 return nil
279279}
280280
281- // writeYAMLFile 校验 YAML 合法性并写入文件 。
281+ // writeYAMLFile 校验 YAML 合法性,通过 unmarshal → marshal 标准化格式后写入文件 。
282282func writeYAMLFile (path , content string ) error {
283- if err := ValidateYAML (content ); err != nil {
283+ normalized , err := NormalizeYAML (content )
284+ if err != nil {
284285 return fmt .Errorf ("生成的 %s 不合法: %w" , filepath .Base (path ), err )
285286 }
286- if err := fileutil .WriteFile (path , []byte (content )); err != nil {
287+ if err := fileutil .WriteFile (path , []byte (normalized )); err != nil {
287288 return fmt .Errorf ("写入 %s 失败: %w" , path , err )
288289 }
289290 return nil
290291}
291292
293+ // NormalizeYAML 通过 unmarshal → marshal 标准化 YAML 格式。
294+ // 解决 LLM 生成的 YAML 存在的缩进不一致、多余空格、换行错乱等问题。
295+ func NormalizeYAML (content string ) (string , error ) {
296+ var data interface {}
297+ if err := yaml .Unmarshal ([]byte (content ), & data ); err != nil {
298+ return "" , err
299+ }
300+ out , err := yaml .Marshal (data )
301+ if err != nil {
302+ return "" , err
303+ }
304+ return string (out ), nil
305+ }
306+
292307// extractModulesFromArchitecture 从 ARCHITECTURE_MAP YAML 中提取模块名列表。
293308// 使用完整相对路径(/ 替换为 _)作为模块标识符,避免不同父目录下同名包冲突。
294309// 例如 "internal/config" → "internal_config", "cmd" → "cmd"。
@@ -317,24 +332,30 @@ func extractModulesFromArchitecture(archYAML string) []string {
317332 return modules
318333}
319334
320- // WriteGeneratedYAML 校验 GeneratedYAML 并写入 .kontext/ 目录。
335+ // WriteGeneratedYAML 校验 GeneratedYAML,标准化格式并写入 .kontext/ 目录。
321336func WriteGeneratedYAML (generated * GeneratedYAML ) error {
322- // 校验 YAML 合法性
323- if err := ValidateYAML (generated .ProjectManifest ); err != nil {
337+ // 标准化 YAML 格式
338+ normalizedManifest , err := NormalizeYAML (generated .ProjectManifest )
339+ if err != nil {
324340 return fmt .Errorf ("生成的 PROJECT_MANIFEST.yaml 不合法: %w" , err )
325341 }
326- if err := ValidateYAML (generated .ArchitectureMap ); err != nil {
342+ normalizedArch , err := NormalizeYAML (generated .ArchitectureMap )
343+ if err != nil {
327344 return fmt .Errorf ("生成的 ARCHITECTURE_MAP.yaml 不合法: %w" , err )
328345 }
329- if err := ValidateYAML (generated .Conventions ); err != nil {
346+ normalizedConv , err := NormalizeYAML (generated .Conventions )
347+ if err != nil {
330348 return fmt .Errorf ("生成的 CONVENTIONS.yaml 不合法: %w" , err )
331349 }
332350
333- // 校验模块契约
351+ // 标准化模块契约
352+ normalizedContracts := make (map [string ]string , len (generated .ModuleContracts ))
334353 for name , content := range generated .ModuleContracts {
335- if err := ValidateYAML (content ); err != nil {
354+ normalized , err := NormalizeYAML (content )
355+ if err != nil {
336356 return fmt .Errorf ("生成的 %s_CONTRACT.yaml 不合法: %w" , name , err )
337357 }
358+ normalizedContracts [name ] = normalized
338359 }
339360
340361 // 写入文件
@@ -352,9 +373,9 @@ func WriteGeneratedYAML(generated *GeneratedYAML) error {
352373
353374 // 写入核心配置文件
354375 files := map [string ]string {
355- filepath .Join (kontextDir , "PROJECT_MANIFEST.yaml" ): generated . ProjectManifest ,
356- filepath .Join (kontextDir , "ARCHITECTURE_MAP.yaml" ): generated . ArchitectureMap ,
357- filepath .Join (kontextDir , "CONVENTIONS.yaml" ): generated . Conventions ,
376+ filepath .Join (kontextDir , "PROJECT_MANIFEST.yaml" ): normalizedManifest ,
377+ filepath .Join (kontextDir , "ARCHITECTURE_MAP.yaml" ): normalizedArch ,
378+ filepath .Join (kontextDir , "CONVENTIONS.yaml" ): normalizedConv ,
358379 }
359380
360381 for path , content := range files {
@@ -365,10 +386,10 @@ func WriteGeneratedYAML(generated *GeneratedYAML) error {
365386 }
366387
367388 // 写入模块契约文件
368- if len (generated . ModuleContracts ) > 0 {
389+ if len (normalizedContracts ) > 0 {
369390 fmt .Println ()
370- fmt .Printf (" 模块契约 (%d 个):\n " , len (generated . ModuleContracts ))
371- for name , content := range generated . ModuleContracts {
391+ fmt .Printf (" 模块契约 (%d 个):\n " , len (normalizedContracts ))
392+ for name , content := range normalizedContracts {
372393 filename := fmt .Sprintf ("%s_CONTRACT.yaml" , name )
373394 path := filepath .Join (kontextDir , "module_contracts" , filename )
374395 if err := fileutil .WriteFile (path , []byte (content )); err != nil {
0 commit comments