@@ -28,20 +28,18 @@ use panda_core::summarizer::embed_batch;
2828
2929// ── helper ────────────────────────────────────────────────────────────────────
3030
31- fn embed_text ( text : & str ) -> Vec < f32 > {
32- embed_batch ( & [ text] )
33- . expect ( "embed_batch failed" )
34- . into_iter ( )
35- . next ( )
36- . expect ( "empty result" )
31+ /// Returns the embedding, or `None` when the BERT daemon is unavailable (CI).
32+ fn embed_text ( text : & str ) -> Option < Vec < f32 > > {
33+ embed_batch ( & [ text] ) . ok ( ) ?. into_iter ( ) . next ( )
3734}
3835
39- fn make_session_with_prior ( cmd : & str , prior_output : & str ) -> SessionState {
36+ /// Returns a session with one recorded turn, or `None` when BERT is unavailable.
37+ fn make_session_with_prior ( cmd : & str , prior_output : & str ) -> Option < SessionState > {
38+ let emb = embed_text ( prior_output) ?;
4039 let mut session = SessionState :: default ( ) ;
41- let emb = embed_text ( prior_output) ;
4240 let tokens = panda_core:: tokens:: count_tokens ( prior_output) ;
4341 session. record ( cmd, emb, tokens, prior_output, false , None ) ;
44- session
42+ Some ( session)
4543}
4644
4745// ── Delta fires for moderately similar outputs ────────────────────────────────
@@ -58,9 +56,11 @@ fn delta_fires_for_similar_but_not_identical_output() {
5856 let prior = format ! ( "{}\n warning: unused variable `x`" , shared) ;
5957 let new_output = format ! ( "{}\n error[E0502]: cannot borrow `self` as mutable" , shared) ;
6058
61- let session = make_session_with_prior ( "cargo" , & prior) ;
59+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
60+ ( Some ( s) , Some ( e) ) => ( s, e) ,
61+ _ => return , // BERT daemon unavailable — skip in CI
62+ } ;
6263 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
63- let new_emb = embed_text ( & new_output) ;
6464
6565 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) ;
6666
@@ -78,9 +78,11 @@ fn new_error_line_present_in_delta_output() {
7878 let prior = format ! ( "{}\n warning: all good" , shared) ;
7979 let new_output = format ! ( "{}\n error[E0308]: mismatched types expected `u32` found `i64`" , shared) ;
8080
81- let session = make_session_with_prior ( "cargo" , & prior) ;
81+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
82+ ( Some ( s) , Some ( e) ) => ( s, e) ,
83+ _ => return ,
84+ } ;
8285 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
83- let new_emb = embed_text ( & new_output) ;
8486
8587 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) . unwrap ( ) ;
8688
@@ -102,9 +104,11 @@ fn repeated_lines_replaced_with_marker() {
102104 let prior = format ! ( "{}\n warning: build succeeded" , shared) ;
103105 let new_output = format ! ( "{}\n error: linker exited with code 1" , shared) ;
104106
105- let session = make_session_with_prior ( "cargo" , & prior) ;
107+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
108+ ( Some ( s) , Some ( e) ) => ( s, e) ,
109+ _ => return ,
110+ } ;
106111 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
107- let new_emb = embed_text ( & new_output) ;
108112
109113 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) . unwrap ( ) ;
110114
@@ -126,9 +130,11 @@ fn same_count_reflects_repeated_lines() {
126130 let prior = format ! ( "{}\n info: build complete" , shared) ;
127131 let new_output = format ! ( "{}\n error: failed to link object files" , shared) ;
128132
129- let session = make_session_with_prior ( "cargo" , & prior) ;
133+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
134+ ( Some ( s) , Some ( e) ) => ( s, e) ,
135+ _ => return ,
136+ } ;
130137 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
131- let new_emb = embed_text ( & new_output) ;
132138
133139 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) . unwrap ( ) ;
134140
@@ -154,9 +160,11 @@ fn new_count_reflects_genuinely_new_lines() {
154160 shared
155161 ) ;
156162
157- let session = make_session_with_prior ( "cargo" , & prior) ;
163+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
164+ ( Some ( s) , Some ( e) ) => ( s, e) ,
165+ _ => return ,
166+ } ;
158167 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
159- let new_emb = embed_text ( & new_output) ;
160168
161169 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) . unwrap ( ) ;
162170
@@ -173,11 +181,17 @@ fn new_count_reflects_genuinely_new_lines() {
173181#[ test]
174182fn delta_does_not_fire_across_different_commands ( ) {
175183 let cargo_output = " Compiling foo v1.0\n error: build failed" ;
176- let session = make_session_with_prior ( "cargo" , cargo_output) ;
184+ let session = match make_session_with_prior ( "cargo" , cargo_output) {
185+ Some ( s) => s,
186+ None => return ,
187+ } ;
177188
178189 let git_output = "On branch main\n nothing to commit, working tree clean" ;
179190 let git_lines: Vec < & str > = git_output. lines ( ) . collect ( ) ;
180- let git_emb = embed_text ( git_output) ;
191+ let git_emb = match embed_text ( git_output) {
192+ Some ( e) => e,
193+ None => return ,
194+ } ;
181195
182196 let delta = session. compute_delta ( "git" , & git_lines, & git_emb) ;
183197
@@ -191,12 +205,17 @@ fn delta_does_not_fire_across_different_commands() {
191205#[ test]
192206fn delta_does_not_fire_for_semantically_unrelated_output ( ) {
193207 let prior = " Compiling foo v1.0\n Compiling bar v2.0\n warning: unused import" ;
194- let session = make_session_with_prior ( "cargo" , prior) ;
208+ let ( session, new_emb) = {
209+ let new_output_str = "test result: FAILED. 3 passed; 1 failed; 0 ignored\n FAILED tests::auth::token_expiry" ;
210+ match ( make_session_with_prior ( "cargo" , prior) , embed_text ( new_output_str) ) {
211+ ( Some ( s) , Some ( e) ) => ( s, e) ,
212+ _ => return ,
213+ }
214+ } ;
195215
196216 // Totally different output: test results (not compilation)
197217 let new_output = "test result: FAILED. 3 passed; 1 failed; 0 ignored\n FAILED tests::auth::token_expiry" ;
198218 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
199- let new_emb = embed_text ( new_output) ;
200219
201220 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) ;
202221
@@ -218,7 +237,10 @@ fn delta_returns_none_for_empty_session() {
218237 let session = SessionState :: default ( ) ;
219238 let output = " Compiling foo v1.0\n error: build failed" ;
220239 let lines: Vec < & str > = output. lines ( ) . collect ( ) ;
221- let emb = embed_text ( output) ;
240+ let emb = match embed_text ( output) {
241+ Some ( e) => e,
242+ None => return ,
243+ } ;
222244
223245 let delta = session. compute_delta ( "cargo" , & lines, & emb) ;
224246
@@ -236,12 +258,13 @@ fn reference_turn_is_correct() {
236258 . join ( "\n " ) ;
237259
238260 let prior = format ! ( "{}\n warning: done" , shared) ;
239- let session = make_session_with_prior ( "cargo" , & prior) ;
240-
241261 // The recorded entry is turn 1 (first record call)
242262 let new_output = format ! ( "{}\n error: new failure" , shared) ;
263+ let ( session, new_emb) = match ( make_session_with_prior ( "cargo" , & prior) , embed_text ( & new_output) ) {
264+ ( Some ( s) , Some ( e) ) => ( s, e) ,
265+ _ => return ,
266+ } ;
243267 let new_lines: Vec < & str > = new_output. lines ( ) . collect ( ) ;
244- let new_emb = embed_text ( & new_output) ;
245268
246269 let delta = session. compute_delta ( "cargo" , & new_lines, & new_emb) . unwrap ( ) ;
247270
0 commit comments