Writing SSPBUF from variable in I2C slave protocol in PIC18
I found a workaround. It is absolutely mind blowing. If I change:

SSPBUF = a;


to

SSPBUF = a+1;


it works. The data+1 goes to the I2C server. I guess it has something to do with the generated assembler code.

Let's analyze the options:

Option 1 - assigning a constant (it works)

The code

SSPBUF = 0x23;


results in:

1548                           ;naplaca.c: 320: SSPBUF = 0x2;
1549  00008A  0E02                  movlw   2
1550  00008C  D00F                  goto    L3
(...)
1661  0000BA                     L3:
1662  0000BA  6EC9                  movwf   4041,c  ;volatile


Option 2 - assigning a variable (does not work)

The code:

unsigned char a = 0x2;
SSPBUF = a;//0x01; //Deliver first byte


results in:

1544                           ;naplaca.c: 318: unsigned char a = 0x2;
1545  000086  0E02                  movlw   2
1546  000088  6E11                  movwf   interruption_handler@a,c
1547                           
1548                           ;naplaca.c: 319: SSPBUF = a;
1549  00008A  C011  FFC9            movff   interruption_handler@a,4041 ;volatile


Option 3 - assigning the result of an expression (works but send data +1)

The code:

unsigned char a = 0x2;
SSPBUF = a+1;//0x01; //Deliver first byte


results in:

1544                           ;naplaca.c: 318: unsigned char a = 0x2;
1545  000086  0E02                  movlw   2
1546  000088  6E11                  movwf   interruption_handler@a,c
1547                           
1548                           ;naplaca.c: 319: SSPBUF = a+1;
1549  00008A  2811                  incf    interruption_handler@a,w,c
1550  00008C  D00F                  goto    L3
1551  00
(...)
1661  0000BA                     L3:
1662  0000BA  6EC9                  movwf   4041,c  ;volatile   


I tried to sum 0, but the compiler optimizes it and make it equals to option 2.
The same happens for a+1-1 and a+2-1-1.

Thus the workaround so far is to send data+1.

Option 4 (volatile variable - does not work) -- edit

The code:

volatile unsigned char a = 0x09;
SSPBUF =  a;// byte1_0 + 1; //0x01; //Deliver first byte


results in:

1634                           ;naplaca.c: 350: volatile unsigned char a = 0x09;
1635  000098  0E09                  movlw   9
1636  00009A  6E11                  movwf   interruption_handler@a,c    ;volatile
1637                           
1638                           ;naplaca.c: 351: SSPBUF = a;
1639  00009C  C011  FFC9            movff   interruption_handler@a,4041 ;volatile
1640                  


Conclusion

It seems to work when the compiler assign value to SSPBUF with movwf. When it uses move, it does not work.

I am posting this as an answer but I will not mark it as the right answer. I hope someone bring some light to this problem.