@@ -125,47 +125,59 @@ describe("add_labels", () => {
125125 const result = await handler (
126126 {
127127 item_number : 456 ,
128- labels : [ { name : "bug" , rationale : "Known crash path" , confidence : "high " , suggest : true } ] ,
128+ labels : [ { name : "bug" , rationale : "Known crash path" , confidence : "HIGH " , suggest : true } ] ,
129129 } ,
130130 { }
131131 ) ;
132132
133133 expect ( result . success ) . toBe ( true ) ;
134134 expect ( result . number ) . toBe ( 456 ) ;
135135 expect ( addLabelsCalls ) . toHaveLength ( 1 ) ;
136- expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ "bug" ] ) ;
136+ expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ { name : "bug" , rationale : "Known crash path" , confidence : "HIGH" , suggest : true } ] ) ;
137137 } ) ;
138138
139- it ( "should send structured label metadata when issue_intents runtime feature is enabled" , async ( ) => {
140- const previousFeatures = process . env . GH_AW_RUNTIME_FEATURES ;
141- process . env . GH_AW_RUNTIME_FEATURES = "issue_intents" ;
142- try {
143- const handler = await main ( { max : 10 } ) ;
144- const addLabelsCalls = [ ] ;
139+ it ( "should send structured label metadata without requiring a runtime feature" , async ( ) => {
140+ const handler = await main ( { max : 10 } ) ;
141+ const addLabelsCalls = [ ] ;
145142
146- mockGithub . rest . issues . addLabels = async params => {
147- addLabelsCalls . push ( params ) ;
148- return { } ;
149- } ;
143+ mockGithub . rest . issues . addLabels = async params => {
144+ addLabelsCalls . push ( params ) ;
145+ return { } ;
146+ } ;
150147
151- const result = await handler (
152- {
153- item_number : 456 ,
154- labels : [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "HIGH" } ] ,
155- } ,
156- { }
157- ) ;
158-
159- expect ( result . success ) . toBe ( true ) ;
160- expect ( addLabelsCalls ) . toHaveLength ( 1 ) ;
161- expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "HIGH" } ] ) ;
162- } finally {
163- if ( previousFeatures === undefined ) {
164- delete process . env . GH_AW_RUNTIME_FEATURES ;
165- } else {
166- process . env . GH_AW_RUNTIME_FEATURES = previousFeatures ;
167- }
168- }
148+ const result = await handler (
149+ {
150+ item_number : 456 ,
151+ labels : [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "HIGH" } ] ,
152+ } ,
153+ { }
154+ ) ;
155+
156+ expect ( result . success ) . toBe ( true ) ;
157+ expect ( addLabelsCalls ) . toHaveLength ( 1 ) ;
158+ expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "HIGH" } ] ) ;
159+ } ) ;
160+
161+ it ( "should normalize lowercase confidence in structured label metadata" , async ( ) => {
162+ const handler = await main ( { max : 10 } ) ;
163+ const addLabelsCalls = [ ] ;
164+
165+ mockGithub . rest . issues . addLabels = async params => {
166+ addLabelsCalls . push ( params ) ;
167+ return { } ;
168+ } ;
169+
170+ const result = await handler (
171+ {
172+ item_number : 456 ,
173+ labels : [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "high" } ] ,
174+ } ,
175+ { }
176+ ) ;
177+
178+ expect ( result . success ) . toBe ( true ) ;
179+ expect ( addLabelsCalls ) . toHaveLength ( 1 ) ;
180+ expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ { name : "bug" , rationale : "Application crashes on file uploads >5MB" , confidence : "HIGH" } ] ) ;
169181 } ) ;
170182
171183 it ( "should accept issue_number as an alias for item_number" , async ( ) => {
@@ -500,6 +512,31 @@ describe("add_labels", () => {
500512 expect ( result . labelsAdded ) . toEqual ( [ "bug" , "enhancement" ] ) ;
501513 } ) ;
502514
515+ it ( "should prefer the metadata-bearing entry when a duplicate label name appears" , async ( ) => {
516+ const handler = await main ( { max : 10 } ) ;
517+ const addLabelsCalls = [ ] ;
518+
519+ mockGithub . rest . issues . addLabels = async params => {
520+ addLabelsCalls . push ( params ) ;
521+ return { } ;
522+ } ;
523+
524+ const result = await handler (
525+ {
526+ item_number : 100 ,
527+ // First "bug" has no metadata; second "bug" carries intent metadata — second should win
528+ labels : [ { name : "bug" } , { name : "bug" , rationale : "Known crash path" , confidence : "HIGH" , suggest : true } ] ,
529+ } ,
530+ { }
531+ ) ;
532+
533+ expect ( result . success ) . toBe ( true ) ;
534+ expect ( result . labelsAdded ) . toEqual ( [ "bug" ] ) ;
535+ expect ( addLabelsCalls . length ) . toBe ( 1 ) ;
536+ // The payload sent to the API must use the spec with metadata, not the plain string
537+ expect ( addLabelsCalls [ 0 ] . labels ) . toEqual ( [ { name : "bug" , rationale : "Known crash path" , confidence : "HIGH" , suggest : true } ] ) ;
538+ } ) ;
539+
503540 it ( "should sanitize and trim label names" , async ( ) => {
504541 const handler = await main ( { max : 10 } ) ;
505542 const addLabelsCalls = [ ] ;
0 commit comments