diff --git a/personal/projects/psychologist-app/session-design.md b/personal/projects/psychologist-app/session-design.md index e5c3b57c..bc7823a7 100644 --- a/personal/projects/psychologist-app/session-design.md +++ b/personal/projects/psychologist-app/session-design.md @@ -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? ## Связанные заметки