@@ -536,6 +536,121 @@ describe('ConfigManager', () => {
536536 } ) ;
537537 } ) ;
538538
539+ describe ( 'removeSkill' , ( ) => {
540+ it ( 'removes the skill entry from the installed array' , async ( ) => {
541+ const config : DevKitConfig = {
542+ version : '1.0.0' ,
543+ environments : [ 'claude' ] ,
544+ phases : [ ] ,
545+ skills : {
546+ installed : [
547+ { registry : 'codeaholicguy/ai-devkit' , name : 'dev-lifecycle' } ,
548+ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' }
549+ ]
550+ } ,
551+ createdAt : '2024-01-01T00:00:00.000Z' ,
552+ updatedAt : '2024-01-01T00:00:00.000Z'
553+ } ;
554+
555+ ( mockFs . pathExists as any ) . mockResolvedValue ( true ) ;
556+ ( mockFs . readJson as any ) . mockResolvedValue ( config ) ;
557+ ( mockFs . writeJson as any ) . mockResolvedValue ( undefined ) ;
558+
559+ const result = await configManager . removeSkill ( 'dev-lifecycle' ) ;
560+
561+ expect ( result . skills ) . toEqual ( {
562+ installed : [
563+ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' }
564+ ]
565+ } ) ;
566+ expect ( mockFs . writeJson ) . toHaveBeenCalled ( ) ;
567+ } ) ;
568+
569+ it ( 'removes skill when skills is an array' , async ( ) => {
570+ const config : DevKitConfig = {
571+ version : '1.0.0' ,
572+ environments : [ 'claude' ] ,
573+ phases : [ ] ,
574+ skills : [
575+ { registry : 'codeaholicguy/ai-devkit' , name : 'dev-lifecycle' } ,
576+ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' }
577+ ] ,
578+ createdAt : '2024-01-01T00:00:00.000Z' ,
579+ updatedAt : '2024-01-01T00:00:00.000Z'
580+ } ;
581+
582+ ( mockFs . pathExists as any ) . mockResolvedValue ( true ) ;
583+ ( mockFs . readJson as any ) . mockResolvedValue ( config ) ;
584+ ( mockFs . writeJson as any ) . mockResolvedValue ( undefined ) ;
585+
586+ const result = await configManager . removeSkill ( 'dev-lifecycle' ) ;
587+
588+ expect ( result . skills ) . toEqual ( {
589+ installed : [
590+ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' }
591+ ]
592+ } ) ;
593+ expect ( mockFs . writeJson ) . toHaveBeenCalled ( ) ;
594+ } ) ;
595+
596+ it ( 'results in an empty installed array when last skill is removed' , async ( ) => {
597+ const config : DevKitConfig = {
598+ version : '1.0.0' ,
599+ environments : [ 'claude' ] ,
600+ phases : [ ] ,
601+ skills : {
602+ installed : [
603+ { registry : 'codeaholicguy/ai-devkit' , name : 'dev-lifecycle' }
604+ ]
605+ } ,
606+ createdAt : '2024-01-01T00:00:00.000Z' ,
607+ updatedAt : '2024-01-01T00:00:00.000Z'
608+ } ;
609+
610+ ( mockFs . pathExists as any ) . mockResolvedValue ( true ) ;
611+ ( mockFs . readJson as any ) . mockResolvedValue ( config ) ;
612+ ( mockFs . writeJson as any ) . mockResolvedValue ( undefined ) ;
613+
614+ const result = await configManager . removeSkill ( 'dev-lifecycle' ) ;
615+
616+ expect ( result . skills ) . toEqual ( { installed : [ ] } ) ;
617+ expect ( mockFs . writeJson ) . toHaveBeenCalled ( ) ;
618+ } ) ;
619+
620+ it ( 'is a no-op when skill name does not exist in installed' , async ( ) => {
621+ const config : DevKitConfig = {
622+ version : '1.0.0' ,
623+ environments : [ 'claude' ] ,
624+ phases : [ ] ,
625+ skills : {
626+ installed : [
627+ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' }
628+ ]
629+ } ,
630+ createdAt : '2024-01-01T00:00:00.000Z' ,
631+ updatedAt : '2024-01-01T00:00:00.000Z'
632+ } ;
633+
634+ ( mockFs . pathExists as any ) . mockResolvedValue ( true ) ;
635+ ( mockFs . readJson as any ) . mockResolvedValue ( config ) ;
636+ ( mockFs . writeJson as any ) . mockResolvedValue ( undefined ) ;
637+
638+ const result = await configManager . removeSkill ( 'nonexistent' ) ;
639+
640+ expect ( result . skills ) . toEqual ( {
641+ installed : [ { registry : 'codeaholicguy/ai-devkit' , name : 'memory' } ]
642+ } ) ;
643+ } ) ;
644+
645+ it ( 'throws when config file is not found' , async ( ) => {
646+ ( mockFs . pathExists as any ) . mockResolvedValue ( false ) ;
647+
648+ await expect ( configManager . removeSkill ( 'dev-lifecycle' ) ) . rejects . toThrow (
649+ 'Config file not found'
650+ ) ;
651+ } ) ;
652+ } ) ;
653+
539654 describe ( 'normalizeSkillsConfig' , ( ) => {
540655 it ( 'normalizes an array to SkillsConfig' , ( ) => {
541656 const result = configManager . normalizeSkillsConfig ( [
0 commit comments