16.0 KB · updated 2026-05-19 · md

obsidian-sync.ru.md

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

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

<!-- translations:start -->

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

<!-- translations:end -->

Статус: предложение (2026-05-17). Этот документ — спецификация дизайна, а не уже реализованная функциональность. Он описывает, как Tesserae мог бы позволить пользователям редактировать спроецированные wiki-страницы в Obsidian, чтобы эти правки переживали следующий project compile. Реализация откладывается до утверждения этого дизайна.

Сегодня экспорт в Obsidian строго односторонний: типизированный граф из .tesserae/graph.json проецируется в vault, а project compile перезаписывает спроецированные файлы. Пользователи просили и обратное направление — отредактировать описание в 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-интерфейс (предлагаемый)

# Pull-only sync (Tier 1a): overlay reader runs as part of compile by default.
tesserae project compile                  # always pulls vault overrides if vault exists

# Inspect what would change before letting compile apply
tesserae project obsidian-sync --dry-run

# Skip the pull for a single compile (recovery mode)
tesserae project compile --no-vault-pull

# Long-running watch (Tier 2)
tesserae project obsidian-sync --watch --vault ~/Documents/tesserae-vault

Поэтапность

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

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

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

Открытые решения до начала реализации

У них есть предложенные значения по умолчанию, но они заслуживают финального прохода перед тем, как ляжет код:

  1. Форма lint-отчёта. Должны ли расходящиеся поля всплывать как отдельный файл .tesserae/diverged-fields.md или как новая секция в существующем 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 можно читать и запрашивать». Короткая секция «Двусторонняя синхронизация» в конце будет ссылаться сюда, как только появится реализация, с одной строкой резюме: «Редактируйте поля в Obsidian — они переживут recompile. См. obsidian-sync.md для полной модели».

До тех пор существующая read-only-оговорка в obsidian.md остаётся — этот дизайн — дорожная карта, а не выпущенная функциональность.