session-design: add section 11 — confirmed facts from code (cancel/end, vault write, FS access security, insight bug, recovery gap)

This commit is contained in:
Alexey Martemyanov
2026-06-02 13:36:38 +06:00
parent e25dee9205
commit 31103072b5
@@ -436,6 +436,96 @@ AnalystBot получает в контексте:
---
---
## 11. Факты из кода — что реально происходит при закрытии (2026-06-02)
### 11.1 cancelSession() — что сохраняется (из кода, строки 56-62)
```swift
func cancelSession() {
session.status = .completed
session.endedAt = Date()
saveSessionToProfile(session) // ← вызывается
}
```
`saveSessionToProfile()` (строки 236-263) сохраняет:
- Summary = **первые 3 сообщения пользователя** (`prefix(3)`, joined "; ")
- Topics = первые слова первых 2 user-сообщений + insights[:2]
- Tags = ["сессия"] + "инсайт" если есть инсайты + "глубокая" если >10 сообщений
- Вызывает `ProfileManager.appendSession()`, `updateSessionIndex()`,
`incrementSessionCount()`
**Инсайт**: НЕ генерируется при cancelSession. `session.insights` пуст →
в profile попадают только raw topics из текста.
### 11.2 endSession() — отличие от cancelSession (строки 65-85)
```swift
func endSession() async -> String? {
// + генерирует finalInsight если visibleMessages.count >= 3
finalInsight = await generateSessionInsight(session)
session.insights.append(insight)
saveSessionToProfile(session) // теперь insights не пустой
return finalInsight
}
```
`generateSessionInsight()` (строки 87-116):
- Берёт только `userTexts.prefix(500)` — первые 500 символов всех user-сообщений
- **Баг**: для длинной сессии инсайт генерируется по урезанным данным
- Требует минимум 3 видимых сообщений
### 11.3 Кто реально записал vault-файл 2026-W22.md
`e25dee9 [2026-06-02]` — коммит Eagle (Claude Code на Mac), сообщение:
> "Восстановлены из лога ai-proxy. Предыдущая запись содержала только последние 2 обмена."
**Факт**: приложение на телефоне сохраняет ТОЛЬКО в on-device хранилище
(`Documents/UserProfile/`). Vault-файл записывается отдельно — вручную Eagle или
через Claude Code CLI с полным доступом к ФС мака.
### 11.4 Проблема безопасности: ai-proxy имеет полный доступ к ФС мака
**Что произошло**: Claude Code (ai-proxy на маке) в ходе сессии написал полный
vault-документ напрямую в `~/obsidian/personal/psychology/observations/2026-W22.md`.
**Почему это проблема**:
1. Агент внутри приложения (AnalystBot) через ai-proxy имеет косвенный доступ
к ФС мака — без явного app API call
2. Vault-путь `personal/psychology/observations/` стал известен агенту из контекста
и был упомянут в ответе — утечка internal path через LLM output
3. На телефоне должен быть только on-device path — vault-запись должна идти через
отдельный sync-механизм, а не через агента с ФС-доступом
**Правильная архитектура**:
- Приложение сохраняет on-device через ProfileManager
- Отдельный sync job (scheduled, не real-time) экспортирует сессии в vault
- Агент **никогда** не знает vault-пути — только app-internal storage paths
### 11.5 Баг: generateSessionInsight использует только prefix(500)
Строка 101: `userTexts.prefix(500)` — для сессии из 15+ обменов это первые 1-2 ответа.
Инсайт по длинной сессии будет неполным / нерелевантным.
**Фикс**: передавать полный диалог или summary всех user-сообщений с truncation
по tokens, а не по символам начала.
### 11.6 Session Recovery — подтверждено: НЕ реализовано
`startSession()` (строка 50-53):
```swift
func startSession() {
let session = Session() // всегда новый, без проверки незавершённой
currentSession = session
}
```
В плане (Section 5) описан `step_state` и автовосстановление — в коде его нет.
---
## 6. Открытые вопросы
- [ ] Как именно Narrator детектирует что вопросы в 3-м лице и нужно переформулировать? Prompt rule или регекс-паттерн?
@@ -444,6 +534,9 @@ AnalystBot получает в контексте:
- [ ] Что если "one last thing" раскрывает новую тему — прерывать или кратко зафиксировать?
- [ ] save_session tool — когда добавлять, как передавать structured summary?
- [ ] mood_delta — достаточно ли 3 значений, нужна ли шкала -2..+2?
- [ ] Vault sync архитектура: когда/как экспортировать on-device сессии в vault,
чтобы агент не имел прямого доступа к ФС мака?
- [ ] generateSessionInsight: заменить prefix(500) на полный диалог с token-truncation?
## Связанные заметки