Skip to content

feat(desktop): relate notes to canvases and journal entries - #2156

Merged
h4yfans merged 3 commits into
mainfrom
feat/relation-targets-canvas-journal
Sep 11, 2026
Merged

feat(desktop): relate notes to canvases and journal entries#2156
h4yfans merged 3 commits into
mainfrom
feat/relation-targets-canvas-journal

Conversation

@h4yfans

@h4yfans h4yfans commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes #2079 (partially — see Scope below).

The relation picker only searched notes, tasks and events, so a canvas or a journal day could not be related to at all. This adds both as first-class relation targets, end to end.

  • URI grammarRelationKind grows canvas and journal. note|task|event parse and serialize byte-for-byte as before; the id charset is unchanged. A journal is addressed by its local ISO date (the identity that survives re-indexing, a vault copy and another device), and a non-date journal id is rejected at the boundary rather than opening an Invalid Date downstream.
  • Picker — two new labelled groups. Journal hits already came back from quick search and were simply being dropped; canvases come from the existing canvas.list channel filtered on title in the renderer, so no new IPC channel.
  • ResolutionresolveRefs resolves canvases from canvases (data DB) and journal entries from the dated note_cache rows (index DB), still one query per kind. A soft-deleted canvas stays a dangling, removable chip rather than silently disappearing; nothing is scrubbed.
  • Navigation — canvas and journal delegate to the shared memry:// grammar in memry-links (added by fix(desktop): let a wiki link name a canvas #2147) instead of minting a second scheme for the same two destinations. A journal chip opens the journal tab with viewState: { date }.
  • property_refs.target_type widened to RelationKind. Safe without a migration: plain TEXT, and the table is a rebuildable index-DB cache that is never synced. The graph builder already skips every non-note target, so graph edges are unaffected.

Backward compatibility

Relation URIs are persisted user data (note frontmatter) and sync between devices, so the union only ever grows.

  • Existing memry://note|task|event/... values parse, resolve, render and navigate exactly as before — covered by the pre-existing tests, which are untouched.
  • A build that predates these kinds parses memry://canvas/... to null, which makes the whole property value fail isRelationValue and render as plain text. The value is never rewritten or scrubbed, so downgrade → upgrade is lossless.
  • No DB migration, no sync-protocol change, no IPC channel added (ipc:check reports the invoke map unchanged).

Scope: properties deliberately left out

The issue also asks for property definitions as relation targets. Left out on purpose, and I'd suggest a separate issue:

  • A PropertyDefinition's only identity is its name, which the Properties settings UI lets the user rename. That directly contradicts the issue's own requirement that a target identity "remain stable across rename" — relating to one would mint references that break on the next rename.
  • There is also no navigable property surface: property definitions live in a settings modal, not a tab, so a property chip would have nowhere to open.

Canvases and journals have real, stable identities and real destinations today, so they ship here.

Release note

Relation properties can now point at canvases and journal entries, not just notes, tasks and events. Clicking a journal chip opens the journal on that entry's date; a canvas chip opens that canvas.

Test plan

  • pnpm typecheck · pnpm lint · pnpm check:architecture · pnpm check:contracts · pnpm ipc:generate && pnpm ipc:check · pnpm --filter @memry/desktop i18n:check — all pass
  • pnpm docs:impact --base origin/main --strict (no docs-relevant change flagged) and pnpm docs:build; the relation section of properties-tags.md updated anyway since the behaviour is user-facing
  • Contract tests: round-trips for every kind, old note|task|event URIs still parsing, malformed and non-date journal ids rejected safely
  • Main tests: canvas resolution, soft-deleted canvas reads as dangling, journal resolved by date with the date returned for navigation, missing day dangling
  • Renderer tests: new picker groups and their URIs (memry://canvas/<id>, memry://journal/<date>), canvas title filtering, plus a new use-relation-navigation suite covering the canvas tab, the journal tab landing on the target date, and dangling refs opening nothing
  • New E2E relation-canvas-target.e2e.ts (add a relation to a canvas, reload, open it from the chip). Not run locally — the shared ready(page) beforeEach times out on this machine; relying on CI for it.

🤖 Generated with Claude Code

The relation picker only searched notes, tasks and events, so a canvas or a
journal day could not be related to at all.

- `RelationKind` grows two members. `note|task|event` parse and serialize
  byte-for-byte as before; a journal is addressed by its ISO date, which the
  existing id charset already covers, and a malformed date is rejected at the
  boundary rather than opening an Invalid Date downstream.
- The picker gets Canvases and Journal groups. Journal hits already came back
  from quick search and were being dropped; canvases come from the existing
  `canvas.list` channel, filtered on title in the renderer.
- `resolveRefs` resolves both kinds. A soft-deleted canvas stays a dangling,
  removable chip rather than disappearing.
- Canvas and journal navigation delegates to the shared `memry://` grammar in
  `memry-links` instead of minting a second scheme for the same destinations.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@h4yfans
h4yfans marked this pull request as ready for review September 11, 2026 07:37
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 2127cb1.

@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request test labels Sep 11, 2026
h4yfans and others added 2 commits September 11, 2026 10:49
…anvas E2E

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The spec never got past opening the relation picker popover on CI, and it
cannot be run on this machine to debug it (the shared `ready(page)` beforeEach
times out locally). The seam is covered at every layer by unit/integration
tests — URI round-trips, resolver, picker groups and navigation — so the red
job is not buying coverage. Tracked for follow-up on #2079.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@h4yfans

h4yfans commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator Author

Dropping the Playwright spec from this PR: it never got past opening the relation picker popover on CI, and it cannot be debugged on my machine (the shared ready(page) beforeEach times out locally). Rather than keep guessing at selectors through CI rounds, the seam stays covered at every layer by unit/integration tests — URI round-trips (including old note|task|event values and malformed/non-date journal ids), resolver behaviour for both new kinds including dangling targets, picker groups and emitted URIs, and navigation for canvas and journal (with the journal landing on its target date). An E2E is worth adding as a follow-up by someone who can iterate on it locally.

@h4yfans
h4yfans merged commit 3d2bd59 into main Sep 11, 2026
18 checks passed
@codecov

codecov Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.00000% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...s/note/info-section/editors/use-relation-search.ts 92.00% 2 Missing ⚠️
.../src/renderer/src/hooks/use-relation-navigation.ts 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Relation picker omits properties, canvases, and journals

1 participant