@@ -69,6 +69,18 @@ describe("command registry", () => {
6969 expect ( def ?. handler ( "" , ctx ) ) . toEqual ( { type : "message" , text : "built-in" } ) ;
7070 } ) ;
7171
72+ it ( "keeps command-specific availability visibility-only" , ( ) => {
73+ registerCommand ( {
74+ name : "unavailable-but-callable" ,
75+ description : "visibility gated" ,
76+ available : ( ) => false ,
77+ handler : ( ) => ( { type : "noop" } ) ,
78+ } ) ;
79+
80+ expect ( listCommands ( ) . map ( ( command ) => command . name ) ) . not . toContain ( "unavailable-but-callable" ) ;
81+ expect ( getCommand ( "unavailable-but-callable" ) ) . toBeDefined ( ) ;
82+ } ) ;
83+
7284 it ( "invokes handler with args and context" , ( ) => {
7385 let receivedArgs = "" ;
7486 let clearCalled = false ;
@@ -102,6 +114,83 @@ describe("registerCommandPlugin", () => {
102114 expect ( getCommand ( "plugin-cmd-a" ) ) . toBeDefined ( ) ;
103115 expect ( getCommand ( "plugin-cmd-b" ) ) . toBeDefined ( ) ;
104116 } ) ;
117+
118+ it ( "re-resolves activation for discovery and execution" , ( ) => {
119+ let active = true ;
120+ registerCommandPlugin (
121+ {
122+ commands : [
123+ {
124+ name : "live-plugin-cmd" ,
125+ description : "live plugin" ,
126+ handler : ( ) => ( { type : "message" , text : "ran" } ) ,
127+ } ,
128+ ] ,
129+ } ,
130+ ( ) => active ,
131+ ) ;
132+
133+ expect ( listCommands ( ) . map ( ( command ) => command . name ) ) . toContain ( "live-plugin-cmd" ) ;
134+ expect ( getCommand ( "live-plugin-cmd" ) ?. handler ( "" , ctx ) ) . toEqual ( {
135+ type : "message" ,
136+ text : "ran" ,
137+ } ) ;
138+
139+ active = false ;
140+ expect ( listCommands ( ) . map ( ( command ) => command . name ) ) . not . toContain ( "live-plugin-cmd" ) ;
141+ expect ( getCommand ( "live-plugin-cmd" ) ) . toBeUndefined ( ) ;
142+
143+ active = true ;
144+ expect ( getCommand ( "live-plugin-cmd" ) ) . toBeDefined ( ) ;
145+ } ) ;
146+
147+ it ( "lets an enabled plugin claim a name ahead of a disabled candidate" , ( ) => {
148+ registerCommandPlugin (
149+ {
150+ commands : [
151+ {
152+ name : "plugin-candidate-collision" ,
153+ description : "disabled candidate" ,
154+ handler : ( ) => ( { type : "noop" } ) ,
155+ } ,
156+ ] ,
157+ } ,
158+ ( ) => false ,
159+ ) ;
160+ registerCommandPlugin (
161+ {
162+ commands : [
163+ {
164+ name : "plugin-candidate-collision" ,
165+ description : "enabled candidate" ,
166+ handler : ( ) => ( { type : "noop" } ) ,
167+ } ,
168+ ] ,
169+ } ,
170+ ( ) => true ,
171+ ) ;
172+
173+ expect ( getCommand ( "plugin-candidate-collision" ) ?. description ) . toBe ( "enabled candidate" ) ;
174+ } ) ;
175+
176+ it ( "never lets a plugin collision replace a built-in command" , ( ) => {
177+ registerCommand ( {
178+ name : "built-in-plugin-collision" ,
179+ description : "built-in" ,
180+ handler : ( ) => ( { type : "noop" } ) ,
181+ } ) ;
182+ registerCommandPlugin ( {
183+ commands : [
184+ {
185+ name : "built-in-plugin-collision" ,
186+ description : "plugin" ,
187+ handler : ( ) => ( { type : "noop" } ) ,
188+ } ,
189+ ] ,
190+ } ) ;
191+
192+ expect ( getCommand ( "built-in-plugin-collision" ) ?. description ) . toBe ( "built-in" ) ;
193+ } ) ;
105194} ) ;
106195
107196describe ( "setHiddenCommands" , ( ) => {
0 commit comments