fix(core): project-scoped forget, dim-safe cosine, precise question detection#25
Conversation
…estion detection
Three correctness fixes found auditing the engine:
- forget(): the processed_files cleanup used `LIKE '%slug%'`, an unanchored
substring match. It also cleared sibling projects (forgetting `…-grasp`
matched `…-grasp-core`) and treated `_`/`%` in a slug as wildcards, forcing
needless re-imports. Now matches the project's transcript directory as an
escaped, anchored prefix (`escape_like` handles Windows backslashes).
- cosine(): `zip` silently computed a truncated dot product when vector
lengths differed. The `embeddings` table stores a per-row `dim`, so a future
model/DIM change can leave stale vectors of another length — those must not
corrupt ranking or semantic edges. Now returns 0.0 on a dimension mismatch.
- is_question(): a bare `contains("what ")` flagged "somewhat" (and similar)
as questions. Now matches interrogatives only at a word boundary.
Each fix has unit-test coverage; full grasp-core suite green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThree correctness fixes in ChangesCorrectness Fixes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/grasp-core/src/lib.rs`:
- Around line 185-195: The `processed_files` cleanup is rebuilding the deletion
prefix from `config.claude_projects_dir`, which misses imports created from a
custom project path. Update the cleanup logic in this import flow to use the
actual stored project/file path that was inserted into
`processed_files.file_path` (the same `file.to_string_lossy()`-based value)
instead of reconstructing it from the configured projects dir. Keep the existing
`LIKE`/`escape_like` approach, but base the prefix on the real path associated
with the imported project so stale rows are removed correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 45ef2a02-c9a9-4112-bd0c-8632f987d06c
📒 Files selected for processing (3)
crates/grasp-core/src/embed.rscrates/grasp-core/src/extractor.rscrates/grasp-core/src/lib.rs
Addresses CodeRabbit's Major finding on PR #25. The processed_files cleanup rebuilt its prefix from claude_projects_dir, which misses transcripts imported from a custom path (`grasp import --path …`) — their processed_files rows live outside claude_projects_dir, so forgetting such a project left stale rows and re-imports were wrongly skipped. Now read projects.path (the real import directory recorded at import time) before deleting the project row, and use it as the LIKE prefix base, falling back to claude_projects_dir.join(slug) when no row exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
What
Three correctness fixes surfaced while auditing the engine (
grasp-core). Each is independent, small, and unit-tested.1.
forget()over-matched sibling projectsThe
processed_filescleanup usedLIKE '%slug%'— an unanchored substring match. Consequences:c--projects-graspalso cleared records forc--projects-grasp-core(substring), forcing a needless full re-import of the sibling._/%in a slug acted as SQL wildcards.Now it matches the project's transcript directory as an anchored, escaped prefix. A new
escape_likehelper escapes%,_, and\so Windows paths stay literal underLIKE … ESCAPE '\'.2.
cosine()silently mis-scored mismatched dimensionsa.iter().zip(b)truncates to the shorter slice, so a stale embedding of a different length produced a bogus (partial) similarity. Theembeddingstable already stores a per-rowdim, so a future model/DIMchange can leave differently-sized vectors behind — those must not corrupt ranking or semantic edges. Now returns0.0on a dimension mismatch.3.
is_question()false-positives on substringsA bare
contains("what ")flagged"somewhat slow"as a question. Now interrogatives match only at a word boundary (start of string or after a non-alphanumeric char).Tests
escape_like_escapes_wildcards_and_backslashescosine_of_mismatched_dimensions_is_zero,cosine_of_identical_unit_vectors_is_onequestion_detection_respects_word_boundariesFull
grasp-coresuite green (29 passed, 2 pre-existing ignored), andgrasp-clibuilds clean.🤖 Generated with Claude Code
Summary by CodeRabbit