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
- ...
Два практических эффекта:
- Пользователи могут аннотировать любую страницу (например, «см. главу 4 моих заметок»), не теряя это при пересборке.
- 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
Поэтапность
| Этап | Объём | Трудозатраты |
|---|---|---|
| 1a | Overlay 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остаётся только проекцией).
Открытые решения до начала реализации
У них есть предложенные значения по умолчанию, но они заслуживают финального прохода перед тем, как ляжет код:
- Форма lint-отчёта. Должны ли расходящиеся поля всплывать как отдельный файл
.tesserae/diverged-fields.mdили как новая секция в существующемlint-report.md? Предложение: отдельный файл, чтобы его можно было диффить в git. - Тип tombstone-узла. Добавить
Stubкак реальный тип схемы или совместить сOpenQuestionчерез дискриминатор_kind: stub? Предложение: реальный тип с именемStub, скрытый из публичных индексов. - Pull-on-compile по умолчанию. По умолчанию ON или OFF? Предложение: ON, когда vault существует по настроенному пути, с однократным подтверждением при первой активации, чтобы пользователи осознанно соглашались.
- Что считается «предыдущей проекцией» для диффа? Снимок, хранящийся в
.tesserae/vault_snapshot.json, или повторная проекция на лету при каждой компиляции? Предложение: снимок, записываемый в конце каждой компиляции. Дешевле и избегает протекания недетерминизма extractor в оверлей. - Многоязычная проекция vault. Сегодняшняя проекция одноязычная (язык источника). Должны ли оверлеи учитывать локаль (например, правка
descriptionв корейском vault применяется только к корейской проекции)? Предложение: вне рамок v1; vault одноязычный, совпадающий с основным языком проекта.
Как это отразится в obsidian.md
Руководство для пользователей остаётся сосредоточенным на «vault можно читать и запрашивать». Короткая секция «Двусторонняя синхронизация» в конце будет ссылаться сюда, как только появится реализация, с одной строкой резюме: «Редактируйте поля в Obsidian — они переживут recompile. См. obsidian-sync.md для полной модели».
До тех пор существующая read-only-оговорка в obsidian.md остаётся — этот дизайн — дорожная карта, а не выпущенная функциональность.