I took a closer look at what happened, then I’m shocked.
Aside from the incorrect termination status, It’s full of inconsistency.
# copy my first 8 lines in my first post, (till JuMP.optimize!(B);)
JuMP.solution_summary(B) # then call this to take a look
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 postponed 0 0.80250 - - - 0s
0 0 postponed 0 0.80250 - - - 0s
0 0 postponed 0 0.80250 - - - 0s
0 2 postponed 0 0.80250 - - - 0s
Explored 3 nodes (7 simplex iterations) in 0.01 seconds (0.00 work units)
Thread count was 8 (of 8 available processors)
Solution count 3: 0.8025 0.8925 1
Model is unbounded
Best objective 8.025000000000e-01, best bound 8.025000000000e-01, gap 0.0000% # 🥎
User-callback calls 122, time in user-callback 0.00 sec
julia> JuMP.solution_summary(B)
* Status
Result count : 3 # 🍅
Termination status : DUAL_INFEASIBLE
Message from the solver:
"Model was proven to be unbounded. Important note: an unbounded status indicates the presence of an unbounded ray that allows the objective to improve without limit. It says nothing about whether the model has a feasible solution. If you require information on feasibility, you should set the objective to zero and reoptimize."
* Candidate solution (result #1)
Primal status : NO_SOLUTION # It seems to be 3 solutions, see 🍅
Dual status : NO_SOLUTION
Objective value : 8.02500e-01 # this value matches Gurobi's, see 🥎's line
Objective bound : 1.00000e+100 # this value does NOT EVEN match Gurobi's `best bound`, see 🥎's line, which doesn't make any sense
Dual objective value : 1.00000e+100