···53535454#### Vector Search
55555656-- [ ] `SemanticSearchRepository` - depends on `EmbeddingService`, `EmbeddingRepository`
5757-- [ ] `search(query, accountDid, {source, maxResults})` - embed query, run `nearestNeighborsF32`, filter by `accountDid` and optional `source`, return `List<SemanticSearchResult>`
5858-- [ ] `SemanticSearchResult` model - `postUri`, `score` (cosine similarity as percentage), `source` (saved/liked)
5959-- [ ] Join results back to Drift `SavedPosts`/`LikedPosts` to hydrate full post JSON for display
5656+- [x] `SemanticSearchRepository` - depends on `EmbeddingService`, `EmbeddingRepository`
5757+- [x] `search(query, accountDid, {source, maxResults})` - embed query, run `nearestNeighborsF32`, filter by `accountDid` and optional `source`, return `List<SemanticSearchResult>`
5858+- [x] `SemanticSearchResult` model - `postUri`, `score` (cosine similarity as percentage), `source` (saved/liked)
5959+- [x] Join results back to Drift `SavedPosts`/`LikedPosts` to hydrate full post JSON for display
60606161### Cubit
6262
···11+/// A single result from a semantic (vector) search.
22+class SemanticSearchResult {
33+ const SemanticSearchResult({
44+ required this.postUri,
55+ required this.score,
66+ required this.source,
77+ required this.postJson,
88+ });
99+1010+ /// AT URI of the post (e.g. at://did:plc:xxx/app.bsky.feed.post/yyy).
1111+ final String postUri;
1212+1313+ /// Cosine similarity expressed as a percentage in [0, 100].
1414+ ///
1515+ /// Derived from the ObjectBox cosine distance: `(1 - distance) * 100`.
1616+ final double score;
1717+1818+ /// Whether this post came from the user's saves ('saved') or likes ('liked').
1919+ final String source;
2020+2121+ /// Raw JSON for the post, fetched from the Drift [SavedPosts] or [LikedPosts]
2222+ /// table for display.
2323+ final String postJson;
2424+2525+ @override
2626+ bool operator ==(Object other) =>
2727+ identical(this, other) ||
2828+ other is SemanticSearchResult &&
2929+ runtimeType == other.runtimeType &&
3030+ postUri == other.postUri &&
3131+ score == other.score &&
3232+ source == other.source &&
3333+ postJson == other.postJson;
3434+3535+ @override
3636+ int get hashCode => Object.hash(postUri, score, source, postJson);
3737+}