@@ -376,16 +376,15 @@ export class Config {
376376 /**
377377 * Remove fields from save data that match system config defaults,
378378 * preventing materialization of admin-managed baselines into user config.
379- * Projects and taskSettings are excluded — projects go through normalization
380- * that changes their shape, and taskSettings always has a default value.
381379 */
382380 private stripSystemDefaults (
383381 data : Record < string , unknown > ,
384382 systemConfig : Partial < AppConfigOnDisk >
385383 ) : void {
386384 const system = systemConfig as Record < string , unknown > ;
387385 for ( const key of Object . keys ( data ) ) {
388- if ( key === "projects" || key === "taskSettings" ) continue ;
386+ // Projects handled separately below due to array-of-tuples structure.
387+ if ( key === "projects" ) continue ;
389388 const dataVal = data [ key ] ;
390389 const sysVal = system [ key ] ;
391390 if ( sysVal === undefined ) continue ;
@@ -420,6 +419,33 @@ export class Config {
420419 }
421420 }
422421 }
422+
423+ // Strip system-provided projects that haven't been modified.
424+ // Projects are arrays of [path, config] tuples — compare by path key.
425+ if ( Array . isArray ( data . projects ) && Array . isArray ( systemConfig . projects ) ) {
426+ const systemProjectMap = new Map < string , string > ( ) ;
427+ for ( const entry of systemConfig . projects ) {
428+ if ( Array . isArray ( entry ) && entry . length >= 2 && typeof entry [ 0 ] === "string" ) {
429+ const [ projectPath , projectConfig ] = entry ;
430+ systemProjectMap . set ( projectPath , JSON . stringify ( projectConfig ) ) ;
431+ }
432+ }
433+ const dataProjects = data . projects as Array < [ string , unknown ] > ;
434+ const filtered = dataProjects . filter ( ( [ projectPath , projectConfig ] ) => {
435+ const systemProjectConfigJson = systemProjectMap . get ( projectPath ) ;
436+ if ( systemProjectConfigJson === undefined ) {
437+ return true ; // User-only project.
438+ }
439+
440+ return JSON . stringify ( projectConfig ) !== systemProjectConfigJson ;
441+ } ) ;
442+
443+ if ( filtered . length === 0 ) {
444+ delete data . projects ;
445+ } else {
446+ data . projects = filtered ;
447+ }
448+ }
423449 }
424450
425451 loadConfigOrDefault ( ) : ProjectsConfig {
0 commit comments