guanghu/docs/adr/0071-external-vault-refresh-and-clean-tab-reopen.md
Guanghu Domestic Migration 9b41d51231
Some checks are pending
Auto-update PR branches / Update open PR branches (push) Waiting to run
CI / Frontend Static Quality Checks (push) Waiting to run
CI / Frontend Tests & Coverage (push) Waiting to run
CI / Rust Tests & Quality Checks (push) Waiting to run
CI / Linux build verification (push) Waiting to run
Deploy docs / Build VitePress site (push) Waiting to run
Deploy docs / Deploy to GitHub Pages (push) Blocked by required conditions
Release (Alpha) / Compute alpha version (push) Waiting to run
Release (Alpha) / Build release artifacts (push) Blocked by required conditions
Release (Alpha) / GitHub Release (alpha) (push) Blocked by required conditions
Release (Alpha) / Update docs and release pages (push) Blocked by required conditions
chore: import sanitized domestic snapshot for REPO-004
Source snapshot: 514ab1975951d94342ea38e64101d5a0f1c51c77
2026-07-17 15:55:28 +08:00

3.4 KiB

type, id, title, status, date, superseded_by
type id title status date superseded_by
ADR 0071 External vault updates reload derived state and reopen the clean active note superseded 2026-04-21 0111

Context

ADR-0002 makes the filesystem the source of truth, and ADR-0043 keeps locally edited frontmatter reactive inside the running UI. But external vault mutations still had a gap. A git pull or an AI agent edit could change notes on disk while the app kept showing stale note-list state, stale derived relationships, or an editor surface that still rendered the pre-refresh BlockNote document.

The fix needed to satisfy a few constraints at once:

  • refresh all vault-derived UI, not just the main note list
  • preserve unsaved local edits instead of clobbering them with disk state
  • reopen the active note from disk when it is safe, even if another file changed, because backlinks, inverse relationships, and other derived surfaces can depend on the whole vault
  • handle the native editor case where an in-place file update requires a full tab reopen to show the fresh document reliably

Decision

All external vault mutations now reconcile through one shared refresh path that reloads vault-derived state and then conditionally reopens the active note from disk.

Tolaria now routes post-pull refreshes and AI-agent file modifications through the same refreshPulledVaultState() helper.

That shared path does the following:

  1. Reload vault.entries, folders, and saved views together.
  2. If there is no active note, stop after the reload.
  3. If the active note has unsaved local edits, keep the current editor buffer and do not replace it from disk.
  4. Otherwise, find the refreshed VaultEntry for the active note and replace the active tab with freshly loaded disk content.
  5. If the active file itself changed in place during the external update, close the tab before reopening it so BlockNote fully remounts onto the new document.
  6. If the active file no longer exists after the reload, close the open tab state instead of leaving a stale editor behind.

Options considered

  • Shared external-refresh reconciler (chosen): one policy for pulls and agent edits, consistent vault-derived UI, and explicit protection for unsaved local edits. Cons: more coupling between sync flows and tab management.
  • Patch only the changed surfaces ad hoc: smaller individual fixes, but high risk of drift between pull handling, agent handling, and future external-write paths.
  • Always force a full app-level reload: simplest correctness story, but too disruptive and more likely to throw away user context unnecessarily.

Consequences

  • Any workflow that mutates the vault externally, such as git pulls or agent writes, should go through the shared refresh reconciler rather than reloading a single surface in isolation.
  • Clean active notes now converge back to on-disk truth automatically after external updates.
  • Unsaved local edits remain protected from external refreshes, even when the rest of the vault reloads.
  • Folder, saved-view, backlink, and inverse-relationship surfaces stay aligned with the refreshed vault, not just the editor tab.
  • Tolaria now treats "refresh after external mutation" as a first-class synchronization concern rather than a per-feature fix.
  • Re-evaluate if the editor gains a reliable in-place document reset API, because that could remove the need for the close-and-reopen step when the active file itself changed.