From 05212133acf9d7912e6591300306c363f887c836 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 9 Jun 2026 10:33:59 -0700 Subject: [PATCH] =?UTF-8?q?docs:=20task-sweep=20end=20state=20=E2=80=94=20?= =?UTF-8?q?wiki-links=20explanation=20+=20changelog=20fragments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs-first commit for the feature/task-sweep branch, which addresses the bulk of the outstanding Hephaestus-project tasks in one sweep. The fragments describe the intended end state; code follows. Also delivers the "understand heph link wiki semantics" task outright: the new [[wiki-links]] explanation card documents body-vs-links-table layering, the manual-wiki-link reconciliation footgun, resolution tiers, and per-client surfaces. Co-Authored-By: Claude Fable 5 --- .../task-sweep-conflicts-ui.feature.md | 1 + .../task-sweep-daemon-status.feature.md | 1 + ...ask-sweep-delete-context-cleanup.bugfix.md | 1 + .../task-sweep-export-wikilinks.feature.md | 1 + .../task-sweep-https-sync.bugfix.md | 1 + .../task-sweep-hub-seeding.feature.md | 1 + .../task-sweep-reparent.feature.md | 1 + .../task-sweep-show-context.feature.md | 1 + .../task-sweep-sync-observability.feature.md | 1 + .../task-sweep-tui-logs.feature.md | 1 + .../task-sweep-tui-rename.feature.md | 1 + .../task-sweep-undoable-delete.feature.md | 1 + .../task-sweep-wiki-links-doc.doc.md | 1 + docs/explanation/explanation.md | 1 + docs/explanation/wiki-links.md | 50 +++++++++++++++++++ 15 files changed, 64 insertions(+) create mode 100644 docs/changelog.d/task-sweep-conflicts-ui.feature.md create mode 100644 docs/changelog.d/task-sweep-daemon-status.feature.md create mode 100644 docs/changelog.d/task-sweep-delete-context-cleanup.bugfix.md create mode 100644 docs/changelog.d/task-sweep-export-wikilinks.feature.md create mode 100644 docs/changelog.d/task-sweep-https-sync.bugfix.md create mode 100644 docs/changelog.d/task-sweep-hub-seeding.feature.md create mode 100644 docs/changelog.d/task-sweep-reparent.feature.md create mode 100644 docs/changelog.d/task-sweep-show-context.feature.md create mode 100644 docs/changelog.d/task-sweep-sync-observability.feature.md create mode 100644 docs/changelog.d/task-sweep-tui-logs.feature.md create mode 100644 docs/changelog.d/task-sweep-tui-rename.feature.md create mode 100644 docs/changelog.d/task-sweep-undoable-delete.feature.md create mode 100644 docs/changelog.d/task-sweep-wiki-links-doc.doc.md create mode 100644 docs/explanation/wiki-links.md diff --git a/docs/changelog.d/task-sweep-conflicts-ui.feature.md b/docs/changelog.d/task-sweep-conflicts-ui.feature.md new file mode 100644 index 0000000..248cca2 --- /dev/null +++ b/docs/changelog.d/task-sweep-conflicts-ui.feature.md @@ -0,0 +1 @@ +Merge conflicts are now actionable: `heph conflicts list` / `heph conflicts resolve --keep local|remote` in the CLI, and a conflicts view in heph-tui (open with `C`) to review and settle divergent task scalars. Resolving with `--keep remote` actually applies the remote value. diff --git a/docs/changelog.d/task-sweep-daemon-status.feature.md b/docs/changelog.d/task-sweep-daemon-status.feature.md new file mode 100644 index 0000000..00d26e2 --- /dev/null +++ b/docs/changelog.d/task-sweep-daemon-status.feature.md @@ -0,0 +1 @@ +`heph daemon status` now surfaces the daemon's runtime config — version, mode, hub URL, sync poll interval, OIDC issuer — and self-update state (enabled, interval, last check time and outcome). diff --git a/docs/changelog.d/task-sweep-delete-context-cleanup.bugfix.md b/docs/changelog.d/task-sweep-delete-context-cleanup.bugfix.md new file mode 100644 index 0000000..b8ba02c --- /dev/null +++ b/docs/changelog.d/task-sweep-delete-context-cleanup.bugfix.md @@ -0,0 +1 @@ +Deleting a task now also tombstones its canonical-context doc, so the orphaned doc no longer lingers in search (FTS) results; restoring the task brings the doc back. diff --git a/docs/changelog.d/task-sweep-export-wikilinks.feature.md b/docs/changelog.d/task-sweep-export-wikilinks.feature.md new file mode 100644 index 0000000..7bf40d6 --- /dev/null +++ b/docs/changelog.d/task-sweep-export-wikilinks.feature.md @@ -0,0 +1 @@ +`heph export` now expands bare `[[NODEID]]` wiki-links to `[[NODEID|Current Name]]` in exported bodies, so exported markdown is readable outside heph. diff --git a/docs/changelog.d/task-sweep-https-sync.bugfix.md b/docs/changelog.d/task-sweep-https-sync.bugfix.md new file mode 100644 index 0000000..0cf2983 --- /dev/null +++ b/docs/changelog.d/task-sweep-https-sync.bugfix.md @@ -0,0 +1 @@ +The hephd sync client can now reach an https hub URL (rustls TLS was not compiled into the HTTP client), and sync errors name the phase and URL instead of a bare "error sending request". diff --git a/docs/changelog.d/task-sweep-hub-seeding.feature.md b/docs/changelog.d/task-sweep-hub-seeding.feature.md new file mode 100644 index 0000000..61faa7a --- /dev/null +++ b/docs/changelog.d/task-sweep-hub-seeding.feature.md @@ -0,0 +1 @@ +Path-A hub seeding: `hephd --owner-id ` establishes the owner on a fresh store, so a hub can be seeded from a device snapshot that shares its owner id; [[set-up-sync-hub]] documents the recipe. diff --git a/docs/changelog.d/task-sweep-reparent.feature.md b/docs/changelog.d/task-sweep-reparent.feature.md new file mode 100644 index 0000000..054814f --- /dev/null +++ b/docs/changelog.d/task-sweep-reparent.feature.md @@ -0,0 +1 @@ +Projects can be re-parented after creation: `heph project move --parent ` (or `--root`), and `m` on a sidebar project in heph-tui opens the parent picker. Cycle-creating moves are rejected. diff --git a/docs/changelog.d/task-sweep-show-context.feature.md b/docs/changelog.d/task-sweep-show-context.feature.md new file mode 100644 index 0000000..20bb00b --- /dev/null +++ b/docs/changelog.d/task-sweep-show-context.feature.md @@ -0,0 +1 @@ +`heph show` on a task now prints the canonical-context doc body alongside the task scalars, instead of a perpetually-null `body` field hiding the real content. diff --git a/docs/changelog.d/task-sweep-sync-observability.feature.md b/docs/changelog.d/task-sweep-sync-observability.feature.md new file mode 100644 index 0000000..0365dcc --- /dev/null +++ b/docs/changelog.d/task-sweep-sync-observability.feature.md @@ -0,0 +1 @@ +Sync observability: cycles that move ops log pulled/applied/pushed counts at info level, recovery after consecutive failures is logged explicitly, and repeated identical failures are throttled instead of spamming the log. diff --git a/docs/changelog.d/task-sweep-tui-logs.feature.md b/docs/changelog.d/task-sweep-tui-logs.feature.md new file mode 100644 index 0000000..a2380af --- /dev/null +++ b/docs/changelog.d/task-sweep-tui-logs.feature.md @@ -0,0 +1 @@ +heph-tui exposes logs properly: `L` opens a scrollable full-history log view for the selected task (the preview pane previously showed only the last five lines). diff --git a/docs/changelog.d/task-sweep-tui-rename.feature.md b/docs/changelog.d/task-sweep-tui-rename.feature.md new file mode 100644 index 0000000..017f2e4 --- /dev/null +++ b/docs/changelog.d/task-sweep-tui-rename.feature.md @@ -0,0 +1 @@ +heph-tui can rename a task in place (`R`), keeping its canonical-context doc's title in step; rename is undoable with `u`. diff --git a/docs/changelog.d/task-sweep-undoable-delete.feature.md b/docs/changelog.d/task-sweep-undoable-delete.feature.md new file mode 100644 index 0000000..3f361f4 --- /dev/null +++ b/docs/changelog.d/task-sweep-undoable-delete.feature.md @@ -0,0 +1 @@ +Undoable delete: a new `node.restore` op un-tombstones a node (last-writer-wins against tombstones by HLC, derived from the op-log — no schema migration). `heph node restore ` and `u` in heph-tui undo task and project deletes. diff --git a/docs/changelog.d/task-sweep-wiki-links-doc.doc.md b/docs/changelog.d/task-sweep-wiki-links-doc.doc.md new file mode 100644 index 0000000..3f47358 --- /dev/null +++ b/docs/changelog.d/task-sweep-wiki-links-doc.doc.md @@ -0,0 +1 @@ +New explanation card [[wiki-links]]: wiki-link semantics — body text vs the links table, why `heph link add … wiki` links get reconciled away, resolution tiers, expand/collapse projection, and how links surface in each client. diff --git a/docs/explanation/explanation.md b/docs/explanation/explanation.md index bbc81dc..45f1cb0 100644 --- a/docs/explanation/explanation.md +++ b/docs/explanation/explanation.md @@ -13,3 +13,4 @@ Background context and design decisions. - [[design]] — Hephaestus design document: vision, data model, architecture, sync, and roadmap - [[task-lifecycle]] — the two-axis task model (lifecycle state × attention), drop vs delete, and where each task shows up - [[hub-spoke-data-evolution]] — why op-based sync lets most new features skip migrations, and when a coordinated SQLite migration is actually required +- [[wiki-links]] — wiki-link semantics: body text vs the links table, `heph link add … wiki` caveats, resolution tiers, expand/collapse projection, and per-client surfaces diff --git a/docs/explanation/wiki-links.md b/docs/explanation/wiki-links.md new file mode 100644 index 0000000..ebbe413 --- /dev/null +++ b/docs/explanation/wiki-links.md @@ -0,0 +1,50 @@ +--- +title: Wiki-Link Semantics +modified: 2026-06-09 +tags: + - explanation +--- + +# Wiki-Link Semantics + +How `[[wiki-links]]` work in the data model, what `heph link add … wiki` actually does, and how links surface in each client. Companion to the frozen build record in [[v1-prototype-tech-spec]] (§5, §6, §8.4). + +## Two layers: body text and the links table + +A wiki-link lives in two places that are kept in sync in one direction: + +1. **The body text** of a node — the source of truth. At rest a link is stored canonically as `[[NODEID]]`, or `[[NODEID|custom text]]` when the author gave explicit display text. Legacy `[[Name]]` links still resolve by title until `heph migrate-links` is run. +2. **The `links` table** — a materialized index. Every time a body is written, `sync_wiki_links` re-extracts the body's links, resolves each target, and *diffs* the node's `wiki`-type link rows to match: rows for targets no longer in the body are tombstoned, rows for new targets are added. This index is what powers backlinks. + +The direction matters: **body → links, never links → body.** + +## What `heph link add wiki` means + +`heph link add … wiki` inserts a `wiki` row directly into the links table *without touching the body*. Because the body is the source of truth, the next body write on `` reconciles the index against the body and **tombstones the manual row** — the link silently disappears. + +So: a manual `wiki` link is at best a temporary annotation on a node whose body never changes, and at worst a footgun. If you want a durable wiki-link, **put `[[dst]]` in the body**. The non-`wiki` link types (`parent`, `blocks`, `tagged`, `in-project`, `canonical-context`, `log-of`) are *only* managed explicitly and are never reconciled against bodies — those are the correct use of `heph link add`. + +## Resolution (who does `[[target]]` point at?) + +Three tiers, first match wins (tech-spec §8.4): + +1. **Node id** — `[[01ABC…]]` resolves to that node if it exists and is live. +2. **Alias** — the `aliases` table. +3. **Exact title** — excluding canonical-context docs, because a task and its context doc share a title; `[[Task Title]]` must resolve to the task. + +Unresolved targets are not an error: the body keeps the text, no link row is created, and a later body write re-syncs once the target exists. + +## Display projection: expand on read, collapse on write + +Bodies at rest store bare ids; humans read names: + +- **Expand (read path):** `node.get` rewrites `[[NODEID]]` → `[[NODEID|Current Name]]`, so a rename is always reflected. +- **Collapse (write path):** `update_node` rewrites `[[NODEID|text]]` → `[[NODEID]]` when `text` still equals the target's current title (an auto-label), preserving genuine custom labels. An unchanged read→write round-trips exactly. +- **Export** also expands ids to readable labels, so exported markdown is human-legible outside heph. + +## How links surface in each client + +- **heph CLI** — `heph show` / `heph context` print bodies through the expand projection; `heph backlinks` (via the `links.backlinks` RPC) lists incoming links from the materialized index. +- **heph-tui** — the preview pane renders the selected task's canonical-context body (expanded labels). Links are display text only today; there is no follow-link navigation in the TUI yet. +- **PWA** — mirrors the TUI's read path through the same hephd RPCs, so it sees the same expanded labels; like the TUI, links are not yet tappable navigation. +- **hephaestus.nvim** — the richest surface: buffer-backed context docs round-trip through expand/collapse, so `[[id|Name]]` spans are editable text that collapses back to canonical ids on save.