Сохранение снимков истории файлов
Краткое описание
Это изменение устраняет пробелы в механизме сохранения A+C для истории файлов /rewind без изменения сохраняемой JSONL-схемы.
Записи file_history_snapshot остаются системными записями, доступными только для добавления (append-only). При возобновлении (Resume) история файлов восстанавливается путем чтения всех записей снимков в линейной истории и дедупликации по promptId по принципу “последний побеждает”. Это означает, что обновленный снимок для того же промпта может быть добавлен позже без перезаписи старых логов.
Запись обновлений снимков
makeSnapshot(promptId) по-прежнему создает снимок на границе хода (turn-boundary), и вызывающий код по-прежнему записывает его явно. Отсутствие случая для последнего хода компенсируется передачей в FileHistoryService опционального callback-а для записи. Когда trackEdit(filePath) успешно добавляет новую резервную копию в последний снимок или восстанавливает сбойную запись резервной копии в этом снимке, он вызывает этот callback с обновленным снимком.
Повторные вызовы trackEdit для уже захваченного (и не сбойного) файла не приводят к новой записи, так как снимок не изменился.
Ошибки записи подавляются и логируются. Редактирование файлов должно оставаться best-effort: сохранение истории файлов не должно приводить к сбоям инструментов редактирования или записи.
Формат сохранения
Версия схемы не добавляется. Существующий payload уже имеет достаточную структуру для обратно совместимого восстановления:
{
"type": "system",
"subtype": "file_history_snapshot",
"systemPayload": {
"snapshots": []
}
}Старые логи без этих записей по-прежнему возобновляются без состояния истории файлов. Некорректные записи снимков пропускаются с предупреждением, а последующие валидные записи остаются пригодными для использования.
Явный флаг isSnapshotUpdate не добавляется. Добавление еще одной записи file_history_snapshot с тем же promptId имеет тот же практический эффект, поскольку SessionService.loadSession() уже применяет дедупликацию по promptId по принципу “последний побеждает”.
Область изменений
Это касается только A+C.
Покрытие для симулированного sed -i в B1 отложено для отдельного PR. Отслеживание общих shell-редактирований, ограничение параллелизма getDiffStats и причины сбоев для каждого файла также отложены. Claude Code сегодня не поддерживает такое поведение, поэтому qwen-code не должен добавлять его в рамках этого прохода по совместимости.
Миграция не требуется, так как формат сохраняемых записей не изменился.