16.8 KB · updated 2026-07-06 · md

obsidian-sync.ru.md

docs/i18n/integrations/obsidian-sync.ru.md

Двусторонняя синхронизация с Obsidian — предлагаемый дизайн

<!-- translations:start -->

English · 한국어 · 中文 · 日本語 · Español · Français · Deutsch

<!-- translations:end -->

Статус: выпущено (Tier 1, v0.5.0). Описанные ниже overlay reader, зоны добавления user-notes, режим watch и удаление осиротевших страниц работают за tesserae vault sync. Эта страница служит и обоснованием дизайна, и руководством пользователя. Мульти-vault федерация (Tier 3) по-прежнему вне области.

Раньше экспорт в Obsidian был строго односторонним: типизированный граф из .tesserae/graph.json проецируется в vault, а project compile перезаписывает спроецированные файлы. obsidian-sync добавляет обратное направление — отредактируйте описание в Obsidian, и оно переживёт повторную компиляцию.

Этот документ объясняет, как это работает, не делая модель данных бессвязной.

Стратегический сдвиг, сформулированный явно

Текущий README отрицает живое редактирование:

Tesserae выбирает компиляцию из исходников вместо живого редактирования. Если хотите редактировать заметки в UI, используйте Logseq или Obsidian.

Двусторонняя синхронизация меняет этот контракт для подмножества полей. Стоит подходить к этому осознанно. Цель — не «Obsidian становится редактором», а «правки пользователя в Obsidian не уничтожаются молча при повторной компиляции».

Основная идея: оверлеи, а не слияния

Вместо попытки слить две расходящиеся копии одного и того же узла, рассматриваем vault как diff-слой поверх проекции:

source markdown  ──extract──▶  base_graph
                                    +
                              vault_overrides     ◀── computed from vault
                                    ↓
                              final_graph  ──project──▶  vault (.md files)

vault_overrides.json лежит в .tesserae/ и вычисляется, а не пишется вручную. На каждой компиляции Tesserae обходит vault, сравнивает каждую спроецированную страницу с тем, что предыдущая проекция записала, и фиксирует каждое внесённое пользователем изменение как запись оверлея. Финальный граф — это base_graph с применёнными оверлеями. Следующая проекция записывает результат обратно на диск.

Round-trip стабильный. Повторная компиляция того же vault без изменений в источнике не даёт никаких диффов.

Владение по полям

У каждого поля узла есть владелец. Владение определяет, что происходит при расхождении источника и vault.

ПолеВладеет источникVault может переопределитьПримечания
id, typeданетКонтролируется схемой; владеет extractor
nameпервичнодаПользователь часто лучше extractor знает каноническое имя
aliasesпервичнодаИз vault — только добавление; записи vault всегда сохраняются
descriptionпервичнодаСамая частая правка в Obsidian
source_pathданетПроисхождение; нельзя стереть редактированием
metadata (заявленные ключи)первичнодаНапр., arxiv_id, github_repo — пользователь может исправить
metadata.user.*n/aдаЗарезервированное пространство имён только для пользовательских ключей; extractor никогда не пишет
Исходящие рёбра (типизированные)данетРёбра живут в онтологии, не в vault
Новые wikilink, которые пишет пользовательn/aдаВсплывают как edge_type=user_link, записываются в граф
Блок <!-- user-notes --> в теленикогда не записываетсявсегда сохраняетсяЗона только для добавления, которой projector никогда не касается

Случаи конфликтов и значения по умолчанию

СлучайПо умолчаниюПочему
description в vault отличается от повторно извлечённого description источникаVault побеждает, логируется в .tesserae/lint-report.md в раздел «diverged fields»Уважение к правкам пользователя: пользователь явно намеренно внёс правку. Аудиторский след позволяет проверить позже.
Исходный файл удалён, но спроецированная страница всё ещё в vaultУдалить узел из графа, занести в .tesserae/orphans.mdИсточник авторитетен по существованию; журнал сирот позволяет решить, восстановить или принять
Пользователь написал wikilink на slug, которого не существуетСоздать tombstone-узел (тип Stub), показать в lint-отчётеНе игнорировать намерение пользователя; пометить для очистки
Пользователь добавил ключ frontmatter, которого схема не знаетСохранить как metadata.user.<key>, никогда не перезаписыватьСовместимо с будущим, не загрязняет типизированный граф
Два vault на разных машинах редактируют один узел, оба синхронизируются через Obsidian SyncВне рамок v1. Побеждает последний пишущий на уровне файловой системы.Настоящая мульти-vault федерация — это Tier 3; откладывается до реального сценария использования

Зона добавления пользовательских заметок

Каждая спроецированная страница получает выделенную зону, которой projector никогда не касается:

> [!quote] Paper
> Headline contribution and method sketch projected from the graph...

<!-- user-notes:start -->

Your notes here. Anything between the markers survives recompile forever.
Wikilinks here become `user_link` edges in the graph on the next pull.

<!-- user-notes:end -->

## Outgoing
- ...

Два практических эффекта:

  1. Пользователи могут аннотировать любую страницу (например, «см. главу 4 моих заметок»), не теряя это при пересборке.
  2. Pull-проход сканирует блок user-notes на наличие wikilink и всплывает их как типизированные онтологией рёбра user_link, давая им достижимость в графе, не загрязняя формальные типы рёбер.

Удалённый транспорт — явная нецель

Tesserae не строит сервер синхронизации, слой аутентификации, демон разрешения конфликтов или хостинг vault. «Двусторонняя» здесь означает «компиляция читает из vault» — то, как vault попадает на машину, выполняющую компиляцию, — забота пользователя, решаемая уже существующими инструментами:

СтекСтоимостьПримечания
Obsidian SyncПлатно, $4–8/месE2E-шифрование, официальный, предельно простой
iCloud / Dropbox / OneDriveВ комплекте с ОСРаботает, но UX конфликтов недружелюбен
SyncthingБесплатно, self-hostedЛучший выбор для одиночного использования на нескольких устройствах
Git (vault закоммичен)БесплатноUX конфликтов — лучший для технических пользователей
LiveSync (плагин CouchDB)Бесплатно, требует серверРеальное время на нескольких устройствах

Все пять совместимы с моделью оверлеев, потому что Tesserae видит vault как файлы на диске, а не как поток мутаций.

CLI-интерфейс

tesserae vault sync применяет правки vault к типизированному графу и заново проецирует:

# Применить оверлей один раз: подтянуть правки пользователя, заново спроецировать в vault.
tesserae vault sync

# Сначала посмотреть, что изменится. Пишет .tesserae/diverged-fields.md и
# НЕ применяет и не перепроецирует.
tesserae vault sync --dry-run

# Указать конкретный vault для этого вызова (порядок разрешения:
# --vault > config.obsidian.vault_path > .tesserae/obsidian_vault/).
tesserae vault sync --vault ~/Documents/tesserae-vault

# Сделать этот путь vault значением по умолчанию для будущих команд.
tesserae vault sync --vault ~/Documents/tesserae-vault --persist-vault

# Долгоживущий watch: заново применять оверлей при каждом изменении vault.
# Ctrl-C для остановки; --poll-interval задаёт частоту опроса (по умолчанию 1.5 с).
tesserae vault sync --watch --poll-interval 1.5

# Удалить спроецированные страницы, исходный узел которых больше не существует
# (projector только перезаписывает, никогда не удаляет). Страницы с user-notes
# сохраняются, если не передать также --force-prune-with-notes.
tesserae vault sync --prune-orphans
tesserae vault sync --prune-orphans --force-prune-with-notes

Слэш-команда /tesserae:obsidian-sync оборачивает это, а tesserae refresh (и макрос /tesserae:refresh) запускает оверлей как последний шаг своей цепочки import → compile → sync.

Статус поставки

ЭтапОбъёмСтатус
1aOverlay reader: обойти vault, построить vault_overrides.json, применить при синхронизации. Расхождения попадают в .tesserae/diverged-fields.md.Выпущено
1bЗоны добавления user-notes: projector никогда не касается блоков <!-- user-notes:start --> ... <!-- user-notes:end -->.Выпущено
2Режим watch: долгоживущий obsidian-sync --watch пересчитывает оверлей в цикле опроса по мере изменения vault.Выпущено
3Мульти-vault федерация: граф хранит происхождение по каждому vault, поддерживает конкурентные правки в синхронизируемых vault.Отложено до реального сценария

Нецели (явно)

  • Сервер синхронизации / аутентификация / хостируемый бэкенд.
  • Реальное совместное редактирование внутри Obsidian (используйте LiveSync, если нужно).
  • Переписывание extractor для round-trip каждого поля — исходный markdown остаётся каноничным для всего, что вне таблицы переопределений.
  • Синхронизация статического HTML-сайта (build-site остаётся только проекцией).

Принятые решения

Это были открытые вопросы на этапе дизайна; выпущенная реализация Tier 1–2 решила их так:

  1. Форма lint-отчёта. Расходящиеся поля всплывают как отдельный файл .tesserae/diverged-fields.md (пишется при --dry-run и на каждом применении), а не как секция lint-report.md, чтобы его можно было диффить в git.
  2. Тип tombstone-узла. Добавить Stub как реальный тип схемы или совместить с OpenQuestion через дискриминатор _kind: stub? Предложение: реальный тип с именем Stub, скрытый из публичных индексов.
  3. Pull-on-compile по умолчанию. По умолчанию ON или OFF? Предложение: ON, когда vault существует по настроенному пути, с однократным подтверждением при первой активации, чтобы пользователи осознанно соглашались.
  4. Что считается «предыдущей проекцией» для диффа? Снимок, хранящийся в .tesserae/vault_snapshot.json, или повторная проекция на лету при каждой компиляции? Предложение: снимок, записываемый в конце каждой компиляции. Дешевле и избегает протекания недетерминизма extractor в оверлей.
  5. Многоязычная проекция vault. Сегодняшняя проекция одноязычная (язык источника). Должны ли оверлеи учитывать локаль (например, правка description в корейском vault применяется только к корейской проекции)? Предложение: вне рамок v1; vault одноязычный, совпадающий с основным языком проекта.

Как это отразится в obsidian.md

Руководство для пользователей остаётся сосредоточенным на «vault можно читать и запрашивать», а затем ссылается сюда ради истории про round-trip, с одной строкой резюме: «Редактируйте поля в Obsidian — они переживут recompile. См. obsidian-sync.md для полной модели».