feat(nvim): live Telescope filter for the [[ link picker (§8.4)
Some checks failed
Build / validate (pull_request) Failing after 10s

Replace the "guess a query, then filter a frozen result set" flow with a
live fuzzy filter over every node when Telescope is present: type to
narrow `node.list`, <CR> inserts the highlighted node, <C-x> creates a
doc named the current prompt (a miss flows straight into making it). The
search-then-`vim.ui.select` two-step stays as the no-Telescope fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-06-03 13:03:02 -07:00
commit d178a657e0
3 changed files with 84 additions and 16 deletions

View file

@ -334,7 +334,7 @@ Field rules: `id`/`kind` are **read-only** (display only); `title`, `attention`,
> **Status: id-addressed links + the `[[` picker are built**; read-expansion/conceal display and the legacy migration are next. Historically bodies stored the human text `[[Title]]` and links materialized by resolving name→id at write time, which is ambiguous (a task and its canonical-context doc share a title — hence the resolution hack in §6/`links::resolve_id`). The fix: **the body stores the canonical node id**, and **no name-addressed link ever enters the DB**.
- ✅ **Resolution is id-first:** `links::resolve_id` checks for an exact live node **id** before alias/title, so `[[NODEID]]` resolves to its node (and a like-named node can't shadow it). Legacy `[[Name]]` links still resolve by name until the migration runs; the canonical-context exclusion hack therefore stays for now (removed once name-resolution is retired).
- ✅ **`heph.nvim` authoring:** typing `[[` (or `:Heph link`) opens a picker (reuses `picker.lua` / Telescope, **no new dependency**) that searches via the `search` RPC and inserts `[[NODEID|Name]]` (labelled → readable + conceal-ready; collapses to bare on save); a **"+ Create new doc"** entry mints a `doc`. Follow (`<CR>`) resolves the id directly.
- ✅ **`heph.nvim` authoring:** typing `[[` (or `:Heph link`) opens a node picker and inserts `[[NODEID|Name]]` (labelled → readable + conceal-ready; collapses to bare on save). With **Telescope** it's a **live fuzzy filter over every node** (`node.list`) — type to narrow, `<CR>` inserts, **`<C-x>` creates a doc named the current prompt** (a miss flows straight into "make it"). Without Telescope it falls back to a `search`-then-`vim.ui.select` prompt with a "+ Create" entry. Follow (`<CR>`) resolves the id directly.
- **At rest (target):** `[[NODEID]]`, or `[[NODEID|custom text]]` when the author wrote explicit display text. The id before the `|` is the target.
- ✅ **Projection (same philosophy as §8.3):** `heph-core::wikilink` (pure, injected id→title) — `node.get` **expands** a bare `[[NODEID]]``[[NODEID|Current Name]]` (every read, so the nvim buffer *and* the TUI preview are readable), and `update_node` **collapses** a `|text` equal to the target's current name back to bare before the CRDT diff (a custom label is preserved as an override). Transform order: read = expand links → prepend frontmatter; write = strip frontmatter → collapse links → store. An unchanged read→write round-trips to the canonical bare id. *(`heph export` still emits raw ids — a later polish.)*
- ✅ **`heph.nvim` display:** `conceal.lua` hides the `[[id|` prefix and the `]]` suffix with conceal extmarks (refreshed on edit), leaving the label as a styled `HephLink` hyperlink; `conceallevel=2` + empty `concealcursor` reveal the raw link on the cursor's line so it stays editable.