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. Открытые вопросы
|
## 6. Открытые вопросы
|
||||||
|
|
||||||
- [ ] Как именно Narrator детектирует что вопросы в 3-м лице и нужно переформулировать? Prompt rule или регекс-паттерн?
|
- [ ] Как именно Narrator детектирует что вопросы в 3-м лице и нужно переформулировать? Prompt rule или регекс-паттерн?
|
||||||
@@ -444,6 +534,9 @@ AnalystBot получает в контексте:
|
|||||||
- [ ] Что если "one last thing" раскрывает новую тему — прерывать или кратко зафиксировать?
|
- [ ] Что если "one last thing" раскрывает новую тему — прерывать или кратко зафиксировать?
|
||||||
- [ ] save_session tool — когда добавлять, как передавать structured summary?
|
- [ ] save_session tool — когда добавлять, как передавать structured summary?
|
||||||
- [ ] mood_delta — достаточно ли 3 значений, нужна ли шкала -2..+2?
|
- [ ] mood_delta — достаточно ли 3 значений, нужна ли шкала -2..+2?
|
||||||
|
- [ ] Vault sync архитектура: когда/как экспортировать on-device сессии в vault,
|
||||||
|
чтобы агент не имел прямого доступа к ФС мака?
|
||||||
|
- [ ] generateSessionInsight: заменить prefix(500) на полный диалог с token-truncation?
|
||||||
|
|
||||||
## Связанные заметки
|
## Связанные заметки
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user