The small adventure
Offline-first systems do not always erase a deleted record immediately. They
often keep a tombstone long enough to tell another device, "this observation was
deleted too." ODE Desktop's structured query API accepts an includeDeleted
option, but the Rust query compiler currently ignores it.
Let's reconnect that switch. This is a contained bug fix with a useful glimpse
into how ODE preserves data history across sync.
Where to start
desktop/src-tauri/src/observation_query.rs
desktop/src-tauri/src/lib.rs (ObservationExtras and
query_observations)
desktop/src/lib/formPreviewBridge.ts (getObservationsByQuery)
packages/observation-query/fixtures/
desktop/AGENTS.md
ObservationExtras.deleted is stored as JSON in the
observation_extras SQLite column. Check how other Desktop code reads that
field before choosing the SQL expression.
Expected behavior
includeDeleted: false excludes rows whose observation extras mark them as
deleted.
includeDeleted: true includes both live rows and deletion tombstones.
- Rows with missing or malformed deletion metadata remain treated as live,
matching the existing default behavior elsewhere in Desktop.
- Filtering must stay in parameterized SQL; do not fetch every row and filter it
in TypeScript.
What to change
- Use the existing
include_deleted argument in
compile_observation_query instead of discarding it.
- Add focused Rust tests for both values and for rows without deletion
metadata. A small in-memory SQLite test is encouraged because it proves the
JSON expression, not just a string fragment.
- Fix the suspicious fixture invocation around
includeDeleted while you are
there, and add or update a fixture if it makes the shared query contract
clearer.
- Keep unrelated query operators and indexes out of scope.
Done when
Verify it
From desktop/src-tauri/:
If TypeScript is changed, also run from desktop/:
pnpm run lint
pnpm run format:check
pnpm test
pnpm run typecheck
What you will meet along the way
You will cross a real ODE boundary: a custom app calls the Formulus-style
bridge, Desktop forwards a structured request to Tauri, and Rust compiles it to
SQLite. You will also meet deletion tombstones, an unglamorous but essential
part of reliable offline synchronization.
AI tools are welcome, not required
AI can propose SQLite JSON syntax, but please verify it against the SQLite
version/features already used by Desktop and prove it with a real query test.
For data code, "the SQL looks plausible" is not verification.
The small adventure
Offline-first systems do not always erase a deleted record immediately. They
often keep a tombstone long enough to tell another device, "this observation was
deleted too." ODE Desktop's structured query API accepts an
includeDeletedoption, but the Rust query compiler currently ignores it.
Let's reconnect that switch. This is a contained bug fix with a useful glimpse
into how ODE preserves data history across sync.
Where to start
desktop/src-tauri/src/observation_query.rsdesktop/src-tauri/src/lib.rs(ObservationExtrasandquery_observations)desktop/src/lib/formPreviewBridge.ts(getObservationsByQuery)packages/observation-query/fixtures/desktop/AGENTS.mdObservationExtras.deletedis stored as JSON in theobservation_extrasSQLite column. Check how other Desktop code reads thatfield before choosing the SQL expression.
Expected behavior
includeDeleted: falseexcludes rows whose observation extras mark them asdeleted.
includeDeleted: trueincludes both live rows and deletion tombstones.matching the existing default behavior elsewhere in Desktop.
in TypeScript.
What to change
include_deletedargument incompile_observation_queryinstead of discarding it.metadata. A small in-memory SQLite test is encouraged because it proves the
JSON expression, not just a string fragment.
includeDeletedwhile you arethere, and add or update a fixture if it makes the shared query contract
clearer.
Done when
both values of
includeDeleted.are touched.
Verify it
From
desktop/src-tauri/:cargo testIf TypeScript is changed, also run from
desktop/:pnpm run lint pnpm run format:check pnpm test pnpm run typecheckWhat you will meet along the way
You will cross a real ODE boundary: a custom app calls the Formulus-style
bridge, Desktop forwards a structured request to Tauri, and Rust compiles it to
SQLite. You will also meet deletion tombstones, an unglamorous but essential
part of reliable offline synchronization.
AI tools are welcome, not required
AI can propose SQLite JSON syntax, but please verify it against the SQLite
version/features already used by Desktop and prove it with a real query test.
For data code, "the SQL looks plausible" is not verification.