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:
@@ -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?
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
|
||||
Reference in New Issue
Block a user