- История: кэш по vault|rel|headOid, fileHistory(vault,file,limit), в диалоге Показать ещё по 60 с сохранением выбора
- Diff считается в QtConcurrent-пуле (parseBlocksWithDiffAsync+blocksReady, stale-guard), спиннер busy; MarkdownView.diffApplied
- commitFile точечно вместо всего хранилища (общий commitFromIndex), autoCommit честный; fileExistedAt + willDelete в подтверждении
- DocumentManager.readTextFile общий (GitManager.workdirContent через него); fileGitStatus через relativePath
- Тесты: пагинация/кэш, existed, commitFile не трогает B, async==sync
- История: убран таб текстового diff — только Просмотр версии с подсветкой; пустые состояния через emptyMessage
- GitManager: удалены fileDiffText/fileDiffHtml (+escHtml), остался fileContentAt/workdirContent/history/restore
- MdParser: удалён словный merge (плейсхолдеры/tokenize/risiko), текст — отдельными del/add как diff; renderInner без сброса codeBlocks, render() — clear+renderInner; убраны save/restore хаки
- Тесты обновлены
- Текст del/add парой сливается в ОДИН блок (change=mod): словный LCS по токенам, плейсхолдеры U+E000/U+E001, рендер, подстановка цветных span только в текстовых узлах; ссылки/URL/код — fallback на два блока чтобы не рвать разметку
- Единые насыщенные цвета везде: rgba(244,63,94,.45)/rgba(34,197,94,.45) — html тинты, строки кода, слова, текстовый diff, легенда (hex с альфой в QML)
- Тесты: text merge, link fallback, цвета
- parseBlocksWithDiff: пара del/add кодовых блоков сливается в ОДИН блок (change=mod) с построчным LCS-diff внутри: удалённые строки — розовая подложка rgba(244,63,94,.45) с −, добавленные — зелёная rgba(34,197,94,.45) с +, неизменные — как были; копируется новое содержимое; fallback — два блока
- Цвета насыщеннее: html тинты #ffd6dd/#b7f5c6 (были бледные), текстовый diff тоже, легенда в тон; на тёмном пузыре светлый текст читается
- Тесты: merge в один блок, маркеры, цвета, copy-нового
- GitManager: fileHistory (список версий с hash/time/message/author), fileContentAt, fileDiffHtml/Text (git_patch_from_buffers, цветной HTML), restoreFile (запись + автокоммит), lastModifiedTime/String, autoCommit, ensureGitignore (.flora/.stfolder)
- HistoryDialog.qml: список версий (время «только что/5 мин назад» + дата dd.MM.yyyy, сообщение, автор, shortHash), diff с легендой (зелёный +/красный -/синий заголовок), превью содержимого, кнопка «Восстановить эту версию» с подтверждением (объясняет что создастся новый коммит и можно вернуться вперёд), «Обновить/Закрыть»
- MainWindow: меню Правка → История файла (Ctrl+H) и Вернуться к предыдущей версии, FileTree ПКМ → История, передача vaultPath/filePath
- EditorPanel: индикатор «🕘» + lastModifiedStr (gitManager.lastModifiedTimeString), debounce autoCommit (2с) при documentSaved, shortcut Ctrl+H
- FileTreePanel: сигнал historyRequested
- CMake: добавлен HistoryDialog.qml в qml модуль
- Тесты: git_history_test — создание v1/v2, история 1→2, diff, восстановление назад к v1 (история 3), вперёд к v2 (4), v3, diff v1→v3, bad hash, other.md не влияет на историю note.md, autoCommit, lastModified, .gitignore; 21/21 зелёных
- Проверено вперёд/назад: v1→v2→восстановление v1→восстановление v2→v3→autoCommit, каждый шаг с проверкой содержимого и истории