Skip to content

Latest commit

 

History

History
161 lines (125 loc) · 20.1 KB

File metadata and controls

161 lines (125 loc) · 20.1 KB

Changelog

2.3.0 (2026-08-03)

Added

  • Ручное разрешение конфликтов: при стратегии «Вручную» (Manual) синхронизация больше не решает конфликты автоматически — открывается диалог с обеими версиями задачи. Доступные действия: оставить версию Obsidian, оставить версию Singularity, создать новую задачу в Singularity (при неоднозначном сопоставлении) или пропустить до следующей синхронизации.
  • Понятный интерфейс конфликт-диалога: каждая версия задачи показывается полями (статус, приоритет, проект, теги, даты, уведомления) в едином порядке, расхождения подсвечиваются бейджами «⚠️», сверху — сводка того, что различается. Даты отображаются в локальном часовом поясе.

Fixed

  • UTF-8 BOM в релизных файлах: BOM, добавленный редакторами в manifest.json/README при сборке релиза, ломал публикацию через release:publish (ошибка JSON.parse). Файлы релиза теперь собираются без BOM, release:publish дополнительно страхуется от него.

2.2.3 (2026-08-02)

Fixed

  • Ошибки 404 в консоли при синхронизации: удалённые в Singularity задачи (и проекты) генерировали ошибки в консоли разработчика и уведомления «⚠️ API 404». Теперь ожидаемые 404 тихо возвращают null — логируются только реальные ошибки API. Логика синхронизации не изменилась: такие задачи корректно пропускаются.

2.2.2 (2026-08-02)

Fixed

  • HTTP 400 при синхронизации: Singularity API v2 отвергает даты без таймзоны ("2026-08-02T15:00:00") и date-only ("2026-08-02") для всех datetime-полей (start, deadline, journalDate, deleteDate). Все даты теперь отправляются с локальным timezone offset (например "2026-08-02T15:00:00+05:00") — создание и обновление задач снова работают.
  • Потеря дат при обновлении: updateTask() молча отбрасывал deadline/start/useTime — изменения сроков и напоминаний не доходили до Singularity. Исправлено.
  • createdDate убран из создания задач: поля нет в API v2 — при отправке всегда возвращался 400.
  • Секция задач стиралась при синхронизации: writeTasksToFile() заменял секцию #### 📝 Tasks пустыми строками, удаляя задачи из файлов проектов. Теперь секция мержится: поля из Singularity обновляются, Obsidian-даты (⏰🛫⏳➕✅❌) сохраняются, несовпавшие строки остаются, новые задачи добавляются в конец.
  • Накопление пустых строк: секция «распухала» на каждой синхронизации (до 5+ пустых строк). Теперь пустые строки схлопываются в одну-единственный разделитель.
  • Исчезающий 📅: срок выполнения сохраняется из существующей строки, если Singularity вернул пустой deadline.

Changed

  • Даты отправляются с локальным timezone offset (ранее — без него), в соответствии с требованиями API. Round-trip сохраняет локальное время (⏰ 2026-08-02 15:00 ↔ start: 2026-08-02T15:00:00+05:00).

2.2.1 (2026-06-17)

Fixed

  • Task disappearance on sync: reverse sync timestamp check (sgMod <= lastKnown) пропускал задачи с externalId, которые только что создал forward sync. Поскольку writeTasksToFile заменяет секцию целиком, пропущенные задачи удалялись из файла. Теперь задачи с externalId никогда не пропускаются — они всегда включаются в tasksToWrite.
  • Unnecessary vault.modify calls: writeTasksToFile() вызывал vault.modify() даже при идентичном содержимом, что меняло file.stat.mtime и провоцировало лишние API-обновления. Теперь содержимое сравнивается перед записью.

2.2.0 (2026-06-17)

Added

  • ⏰ Reminder support: поле reminderDate (эмодзи ⏰) — дата и время напоминания. Вычисляется из notifies + deadline (reverse sync) или из ⏰ в строке задачи (forward sync).
  • notifies → ⏰ forward mapping: при forward sync ⏰ + 📅 конвертируются в массив notifies (минуты до дедлайна). Пользователь может редактировать ⏰ — изменения попадут в Singularity.
  • start → ⏰ mapping: если start в Singularity содержит время и notifies задан — маппится в ⏰ (а не в ⏳). Время только в ⏰ — совместимо с Obsidian Tasks Plugin.
  • Standard task format: formatTaskLine() генерирует задачи в строгом порядке: #todo desc #tags ➕ ⏰ 🛫 ⏳ 📅 🔼 #notify.
  • StableHash (dedup): computeStableHash() — хеш описания без метаданных (теги, даты, эмодзи). При изменении описания задача перелинковывается через TaskStore вместо создания дубликата.
  • Project transfer: перемещение задачи между проектными файлами + изменение описания корректно обновляет projectId в Singularity через stableHash fallback.
  • Normalize task order: normalizeTaskLines() перезаписывает строки задач после forward sync в стандартном порядке.
  • Quiet API mode: _req() принимает quiet — подавляет console.error и Notice для ожидаемых 404 (используется в setHabitProgress()).

Fixed

  • Tasks wiped on sync: writeTasksToFile() с пустым массивом задач стирал секцию #### 📝 Tasks. Теперь if (processed.length === 0) continue; предотвращает запись пустых массивов.
  • Completed tasks not syncing: forward sync архивировал задачи в SG, но reverse sync пропускал их (timestamp match). Добавлен трекинг _archivedIds — reverse sync обрабатывает заархивированные задачи.
  • ⏰ without notifies: start с временем генерировал ⏰ даже без notifies в API. Теперь reminderDate устанавливается только если notifies.length > 0.
  • Time loss on 🛫/📅: formatTaskLine() использовал .split(" ")[0] для startDate/dueDate, теряя время. Исправлено — время отображается только в ⏰.
  • Habit progress 404 Notice: _req() показывал Notice для ожидаемого 404 при PATCH привычек. Добавлен quiet режим.
  • generateTaskId regex order: emoji-даты теперь-stripаются перед эмодзи приоритета (порядок ALL_EMOJI_DATE_RE → ALL_EMOJI_RE).
  • ⏰ only from start: ⏰ теперь ТОЛЬКО из поля start (ранее fallback из deadline - notifies).
  • #notify from ⏰ only: #notify генерируется только из start, не из deadline - start.
  • Local time to API: formatDateForApi() отправляет локальное время без Z (Singularity ожидает local time, не UTC).
  • notifies[0] for ⏰: если ⏰ задан без #notify → отправляется notifies: [0] (напомнить ровно в время ⏰).

Changed

  • notify (singular) и alarmNotify: read-only в API, больше не отправляются при создании задач.
  • Reverse sync timestamp skip: reverse sync пропускает SG-задачи, не изменённые с последней синхронизации (modificatedDate <= lastModifiedSingularity).

2.0.1 (2026-05-19)

Fixed

  • Cancelled task support: строки [-] теперь корректно парсятся и записываются. Добавлен статус TaskStatus.Cancelled (checked=2).
  • Priority display: 🔺 используется для всех задач высокой важности (вместо ⏫). Оба символа ⏫ и 🔺 парсятся как Priority.High.
  • Null-propagation в API-клиенте: значения null корректно отправляются в API для очистки полей (даты, теги). Защита от случайной зачистки SG-тегов пустым массивом.
  • Round-trip стабильность: Phase 2a guard проверяет статус задачи в SG перед skip-ом — предотвращает ложное срабатывание на основе хеша.
  • Soft-delete защита: syncDeletedObsidianTasks() проверяет refCount SG-задачи, не удаляет при наличии других ссылок.
  • lastModifiedSingularity сохранение: поле больше не теряется — сохраняется во всех upsert-операциях, гарантируя корректную работу Phase 2a.
  • forward/reverse изоляция: _failedIds трекает упавшие forward-задачи, reverse sync пропускает их — ошибки forward не затираются.
  • Done date из journalDate: ✅ теперь получает дату из journalDate (а не start).
  • Date-only без дублирования эмодзи: date-only задачи не получают дублирующие 🛫/⏳.
  • Строгое сравнение тегов: getTagName использует точное совпадение, а не includes(), предотвращая ложное матчинг.
  • projectTag в syncHash: добавлен в содержимое хеша для корректного отслеживания перемещений между проектами.
  • 404-handling: softDeleteTask/archiveTask возвращают null при 404 без Notice/console.error.

2.0.0 (2026-05-19)

Added

  • Per-project task files: задачи каждого проекта хранятся в отдельном файле /project/{название}.md. Задачи без проекта — в /tasks/tasks.md. Файл = принадлежность к проекту.
  • Section-aware I/O: секция #### 📝 Tasks (настраиваемый маркер) — единственное место для задач в файлах проектов. Остальное содержимое файла (frontmatter, описание, другие секции) сохраняется.
  • Frontmatter singularity-id: автоматическая привязка файлов Obsidian к проектам Singularity. Позволяет отслеживать переименования проектов.
  • Auto-create проектов: forward sync создаёт проекты в Singularity, если Obsidian-задача ссылается на проект, которого нет в SG.
  • Rename detection: при переименовании проекта в Singularity reverse sync переименовывает соответствующий файл в Obsidian.
  • Create/Update Project API: POST /project, PATCH /project/{id}.
  • Теги проектов в Singularity: при синхронизации forward sync создаёт тег с именем проекта в Singularity (для кросс-фильтрации).
  • tasksSectionMarker в настройках: пользователь может настроить маркер секции задач (по умолчанию #### 📝 Tasks).

Changed

  • Модель связывания проектов: принадлежность к проекту определяется файлом, а не тегом. Тег #my-project в строке задачи больше не нужен — достаточно поместить задачу в /project/My Project.md.
  • extractProjectTag(): без эвристики первого не-todo тега. Только контекст файла определяет projectTag. Для задач из tasks.md → null.
  • processTask(): название проекта больше не добавляется в obsidianTags. projectTag заполняется, но не выводится как тег.
  • writeTasks(): группировка задач по projectTag, роутинг в per-project файлы через vaultWriter.writeTasksToFile().
  • formatTaskLine(): фильтрует projectTag из regularTags — тег проекта не выводится в строку задачи.
  • ensureProjectFiles(): читает frontmatter для singularity-id, переименовывает файлы при смене названия проекта, добавляет frontmatter в существующие файлы.
  • resolveTags(): создаёт тег проекта в Singularity (ранее projectTag пропускался).

Migration from v1.x

  • Задачи в tasks.md с тегом #my-project теряют привязку к проекту. Перенесите их в /project/My Project.md вручную.
  • После первого sync задачи с externalId автоматически мигрируют в соответствующие проектные файлы через reverse sync.
  • Проектные файлы без singularity-id получат его автоматически при ближайшей синхронизации.

1.2.6 (2026-05-17)

Fixed

  • Created date preservation: Если задача уже имеет ➕ в Obsidian — дата создания сохраняется при синхронизации. Для новых задач из Singularity ставится сегодняшняя дата.
  • UTC→Local conversion: utcIsoToLocalDate() конвертирует все date-only поля (createdDate, deadline, journalDate, deleteDate) из UTC ISO в локальный часовой пояс.

1.2.5 (2026-05-17)

Fixed

  • Date-only scheduled/start dates: Reverse sync больше не теряет ⏳ или 🛫 когда дата без времени. Для date-only start проставляются оба поля.

1.2.4 (2026-05-17)

Fixed

  • Priority emoji position: Эмодзи приоритета (🔺⏫🔼🔽⏬) перемещён после всех emoji-дат для совместимости с плагином Obsidian Tasks.

1.2.3 (2026-05-17)

Fixed

  • Reverse sync blocked: Reverse sync теперь обрабатывает задачи, уже существующие в Obsidian. Ранее setSyncedObsidianIds получал все ID, из-за чего reverse sync полностью пропускал задачи, которые forward sync не создавал.
  • Done-статус из Singularity: Reverse sync включает архивированные задачи (includeArchived=true). Задачи, отмеченные выполненными в Singularity, теперь отмечаются [x] в Obsidian.
  • Возврат из архива: Forward sync проверяет checked статус SG-задачи. Если в SG задачу вернули в невыполненные, forward sync не архивирует её повторно.
  • Undone в Obsidian: Если SG говорит checked=0 (не выполнено), reverse sync обновляет строку в Obsidian обратно в [ ] без ✅.
  • Duplicate строк в файле: extractLineDescription и _emojiDatesRe исправлены — больше не оставляют :00.000 в extracted description, не плодят дубликаты.
  • API key leak: TaskStore.saveFn скрабит singularityApiKey и сохраняет syncState + habitState.
  • Conflict resolver: Парсинг modificatedDate через parseSgDate() — корректно обрабатывает ISO-строки, Unix-секунды и Unix-миллисекунды.
  • Ошибки инициализации: Guard на view.loadState, null-safe loadData() в resetAndSync.

1.2.2 (2026-05-15)

Added

  • Auto-create /project/ folder and project notes on first sync: ensureProjectFiles() создаёт папку /project/ и .md файлы для каждого проекта из Singularity, если их ещё нет. Файлы содержат название, эмодзи и описание проекта.
  • Tasks plugin prerequisite: В README добавлен раздел с требованием установки плагина Obsidian Tasks.

Changed

  • _projectCache дополнен _projectsFull для хранения полных данных проектов (emoji, note).

Fixed

  • Version badge in README: Обновлён до 1.2.2 в обоих README.

1.2.1 (2026-05-15)

Fixed

  • 400 error on task sync: maxCount=5000 превышал лимит API (max 1000) → GET /task возвращал 400. Исправлено до 1000.
  • Silent error swallowing: Ошибки в forward-sync и reverse-sync проглатывались пустыми catch {} без логирования. Добавлен console.error.
  • Duplicate tasks in reverse sync: Reverse sync не фильтровал задачи, только что созданные forward sync, что приводило к дублям. Добавлен syncedObsidianIds.
  • Empty PATCH body: updateTask() не обрабатывал externalId, из-за чего вызов updateTask(sgId, { externalId }) отправлял пустой body {} → API возвращал 400.
  • Missing contentType: requestUrl() Obsidian не получал contentType: "application/json" — Content-Type из headers мог игнорироваться.

Added

  • AGENTS.md — инструкция для OpenCode-сессий (GitFlow, команды, архитектура, API-спецификация, MCP-конвенции).

Changed

  • updateTask() теперь принимает externalId и выбрасывает ошибку при пустом теле запроса.
  • updateExisting() проставляет externalId при матчинге задач по описанию.
  • Улучшена диагностика: new Notice с телом ответа API при 400-ошибках.