@@ -171,6 +171,39 @@ describe("writeCodexBundle", () => {
171171 expect ( config ) . toContain ( "[user]" )
172172 } )
173173
174+ test ( "migrates unmarked legacy format (# Generated by compound-plugin)" , async ( ) => {
175+ const tempRoot = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "codex-unmarked-" ) )
176+ const codexRoot = path . join ( tempRoot , ".codex" )
177+ const configPath = path . join ( codexRoot , "config.toml" )
178+
179+ // Simulate old writer output: entire file was just the generated config
180+ await fs . mkdir ( codexRoot , { recursive : true } )
181+ await fs . writeFile ( configPath , [
182+ "# Generated by compound-plugin" ,
183+ "" ,
184+ "[mcp_servers.old]" ,
185+ 'command = "old"' ,
186+ "" ,
187+ ] . join ( "\n" ) )
188+
189+ const bundle : CodexBundle = {
190+ prompts : [ ] ,
191+ skillDirs : [ ] ,
192+ generatedSkills : [ ] ,
193+ mcpServers : { fresh : { command : "new" } } ,
194+ }
195+
196+ await writeCodexBundle ( codexRoot , bundle )
197+
198+ const config = await fs . readFile ( configPath , "utf8" )
199+ expect ( config ) . not . toContain ( "# Generated by compound-plugin" )
200+ expect ( config ) . not . toContain ( "[mcp_servers.old]" )
201+ expect ( config ) . toContain ( "# BEGIN Compound Engineering plugin MCP" )
202+ expect ( config ) . toContain ( "[mcp_servers.fresh]" )
203+ // Should have exactly one BEGIN marker (no duplication)
204+ expect ( config . match ( / # B E G I N C o m p o u n d E n g i n e e r i n g p l u g i n M C P / g) ?. length ) . toBe ( 1 )
205+ } )
206+
174207 test ( "strips stale managed block when plugin has no MCP servers" , async ( ) => {
175208 const tempRoot = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "codex-stale-" ) )
176209 const codexRoot = path . join ( tempRoot , ".codex" )
@@ -443,6 +476,40 @@ describe("mergeCodexConfig", () => {
443476 expect ( result ) . not . toContain ( "# BEGIN" )
444477 } )
445478
479+ test ( "strips unmarked legacy format (# Generated by compound-plugin)" , ( ) => {
480+ const existing = [
481+ "# Generated by compound-plugin" ,
482+ "" ,
483+ "[mcp_servers.old]" ,
484+ 'command = "old"' ,
485+ "" ,
486+ ] . join ( "\n" )
487+
488+ const result = mergeCodexConfig ( existing , "[mcp_servers.new]\ncommand = \"new\"" ) !
489+ expect ( result ) . not . toContain ( "# Generated by compound-plugin" )
490+ expect ( result ) . not . toContain ( "[mcp_servers.old]" )
491+ expect ( result ) . toContain ( "# BEGIN Compound Engineering plugin MCP" )
492+ expect ( result ) . toContain ( "[mcp_servers.new]" )
493+ } )
494+
495+ test ( "preserves user config before unmarked legacy format" , ( ) => {
496+ const existing = [
497+ "[user]" ,
498+ 'model = "gpt-4.1"' ,
499+ "" ,
500+ "# Generated by compound-plugin" ,
501+ "" ,
502+ "[mcp_servers.old]" ,
503+ 'command = "old"' ,
504+ ] . join ( "\n" )
505+
506+ const result = mergeCodexConfig ( existing , "[mcp_servers.new]\ncommand = \"new\"" ) !
507+ expect ( result ) . toContain ( "[user]" )
508+ expect ( result ) . not . toContain ( "# Generated by compound-plugin" )
509+ expect ( result ) . not . toContain ( "[mcp_servers.old]" )
510+ expect ( result ) . toContain ( "[mcp_servers.new]" )
511+ } )
512+
446513 test ( "returns null when no existing content and no mcpToml" , ( ) => {
447514 expect ( mergeCodexConfig ( "" , null ) ) . toBeNull ( )
448515 } )
0 commit comments