Skip to content

Commit ccc72f3

Browse files
committed
chore(release): v0.6.3 — FTS5 trigger correctness (closes #22 #40 #41 #42)
V007 migration + 10-trigger correctness pass closes four V006 bugs surfaced by the 2026-04-17 codex adversarial audit. Switch from contentless to external-content FTS5 + universal joined-live-state reinsert invariant makes fire-order irrelevant. Phase commit log: - feat(db): V007 FTS5 trigger correctness — bundled red + green (26af7e2) - fix(db): v0.6.3 code-quality polish — test tokens + WHY comments + consts (265982b) - test(db): v0.6.3 integration — multi-location + soft-delete + idempotence + combined-tx + tag-rename (b1ba1c8) - test(db): proptest — FTS5 search invariant across tag churn (fa8a740) - ci: drop release-plz-pr job (2d63597) - build: move Tauri env to cargo/justfile (646d6c9) Review-fix commits: 1 (265982b) addressing Opus code-quality findings; Rule 3 satisfied. Tests: 81 perima-db + 68 vitest green; full just ci green with no env-export prefix (post 646d6c9). Bundling: Tasks 1+2 bundled because pre-commit runs full just ci (red commits blocked by no-no-verify rule). Audit trail in 26af7e2 body. Hook split to fix this is tracked as GH issue #52 / task #63. headless-tested: yes (cargo test + proptest 256 cases + just ci; no Tauri runtime)
1 parent fa8a740 commit ccc72f3

3 files changed

Lines changed: 29 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@ roadmap milestone triggers `1.0.0`.
1212

1313
## [Unreleased]
1414

15+
## [0.6.3] — 2026-04-17
16+
17+
### Fixed
18+
19+
- **#40 FTS5 contentless-delete blank payloads.** V006's sync triggers tried to remove old tokens with empty-string payloads on a contentless FTS5 table — a silent no-op. Stale tokens accumulated on metadata updates and tag detaches.
20+
- **#41 tag attach on metadata-less file.** `search_rowid_map` only seeded on `file_metadata` insert, so tag attach on a file without metadata was silently ignored until rebuild.
21+
- **#22 FTS5 stale-rename.** No `file_locations` UPDATE trigger — rename (same hash, new path) left old path indexed.
22+
- **#42 hash change at same path.** No trigger on `file_locations.blake3_hash` change — replace-in-place left stale FTS doc.
23+
24+
### Changed
25+
26+
- **V007 migration: external-content FTS5.** Switch from contentless (`content=""`) to external-content (`content='search_content'`). External-content supports `INSERT INTO search_index(search_index, rowid) VALUES('delete', rowid)` — delete-by-rowid without needing OLD column values. `search_rowid_map` dropped; the new `search_content` materialised table takes its role.
27+
- **Ten triggers in six logical categories** cover every indexable mutation surface. Trigger 2 is split 2a/2b/2c by WHEN-gate (hash change, rename, soft-delete). Universal invariant: every trigger body reinserts `search_content` from joined live state (never `NEW.*` for column values), so fire-order is irrelevant across same-transaction multi-table updates.
28+
- **Representative-selection rule:** first-seen active `file_locations` per hash, tiebroken by `id ASC`. Consistent across bulk-populate, rebuild, trigger 2b guard, trigger 2c re-point, and `search()` join.
29+
- **SearchRepository::rebuild()** rewritten to match new schema.
30+
- **Build env cleanup** (`646d6c9`): `.cargo/config.toml` + `justfile` exports eliminate the per-command `export RUSTFLAGS=... export PKG_CONFIG_PATH=...` ritual. `just ci` now works from a plain shell.
31+
- **release-plz-pr job dropped** from `.github/workflows/release-plz.yml` (`2d63597`). We use direct `chore(release):` commits, not PR-gated releases. Revisit at v1.0 ceremony.
32+
33+
### Notes
34+
35+
- **Migration on launch** re-indexes your library. Transparent to end-users but may add a one-time delay on first launch after upgrade for large libraries (>100k files). Progress logging tracked as post-v1 polish.
36+
- **Multi-location semantics unchanged:** one FTS doc per hash, indexed under first-seen active location (v0.6.0 rule). Multi-path indexing remains out of scope. Non-representative location renames don't affect search.
37+
- **32 new tests** landed (4 regression + 6 integration + 1 proptest w/ 256 cases by default).
38+
1539
## [0.6.2] — 2026-04-17
1640

1741
### Fixed
@@ -489,7 +513,8 @@ tuning filed as follow-up (see Project section below).
489513
`cli`, `desktop`, `ci`, `deps`, `docs`, `release`) rather than development
490514
milestones.
491515

492-
[Unreleased]: https://github.com/utof/perima/compare/v0.6.2...HEAD
516+
[Unreleased]: https://github.com/utof/perima/compare/v0.6.3...HEAD
517+
[0.6.3]: https://github.com/utof/perima/releases/tag/v0.6.3
493518
[0.6.2]: https://github.com/utof/perima/releases/tag/v0.6.2
494519
[0.6.1]: https://github.com/utof/perima/compare/v0.6.0...v0.6.1
495520
[0.6.0]: https://github.com/utof/perima/compare/v0.5.1...v0.6.0

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ members = ["crates/*"]
33
resolver = "3"
44

55
[workspace.package]
6-
version = "0.6.2"
6+
version = "0.6.3"
77
edition = "2024"
88
rust-version = "1.85"
99
license = "MIT OR Apache-2.0"
@@ -30,7 +30,7 @@ missing_errors_doc = "warn"
3030
# WHY workspace-path dep for perima-media: release-plz + other crates
3131
# (perima CLI) need it reachable via `workspace = true` so bumps
3232
# propagate correctly via the workspace graph.
33-
perima-media = { path = "crates/media", version = "0.6.2" }
33+
perima-media = { path = "crates/media", version = "0.6.3" }
3434
anyhow = "1"
3535
thiserror = "2"
3636
serde = { version = "1", features = ["derive"] }

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "perima-desktop",
33
"private": true,
4-
"version": "0.6.2",
4+
"version": "0.6.3",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

0 commit comments

Comments
 (0)