···23232424 /// Search for posts semantically similar to [query].
2525 ///
2626- /// Returns an empty list when [EmbeddingService.isAvailable] is false or
2727- /// when [query] is blank.
2626+ /// Returns an empty list when [EmbeddingService.isAvailable] is false
2727+ /// or when [query] is blank.
2828 ///
2929 /// [source] narrows results to 'saved', 'liked', or both when null.
3030 /// [maxResults] caps the number of results (default 20).
···4949 final results = <SemanticSearchResult>[];
5050 for (final result in rawResults) {
5151 final post = result.object;
5252- // Cosine distance is in [0, 2]; similarity = 1 - distance, clamped to [0, 1].
5352 final similarity = (1.0 - result.score).clamp(0.0, 1.0);
5453 final scorePercent = similarity * 100.0;
5554
···198198 expect(results, hasLength(1));
199199 expect(results.first.source, equals('liked'));
200200 final decoded = jsonDecode(results.first.postJson) as Map<String, dynamic>;
201201- // liked post JSON has a nested 'post' key
202201 expect((decoded['post'] as Map<String, dynamic>)['uri'], equals('at://did/post/2'));
203202 });
204203···216215 test('identical-vector query produces near-100% score', () async {
217216 await insertSavedPost('at://did/post/1', 'did:plc:user');
218217219219- // Query with the same unit vector the post was indexed with.
220218 final svc = EmbeddingService.forTesting((_) async => _unitVector());
221219 await svc.initialize();
222220 final repo = makeRepo(service: svc);
223221 final results = await repo.search('hello', 'did:plc:user');
224222225223 expect(results, isNotEmpty);
226226- // Score should be very close to 100%.
227224 expect(results.first.score, greaterThan(90.0));
228225 });
229226···275272 });
276273277274 test('skips results whose postJson cannot be found in Drift', () async {
278278- // Insert embedding in ObjectBox but NOT in Drift.
279275 embeddingRepo.upsert(
280276 EmbeddedPost(
281277 postUri: 'at://did/post/orphan',
···290286 final repo = makeRepo();
291287 final results = await repo.search('hello', 'did:plc:user');
292288293293- // The orphaned result is silently skipped.
294289 expect(results, isEmpty);
295290 });
296291