[2026-05-16] reflect-app: voice, scheduling, agent tools, session index docs

This commit is contained in:
Alexey Martemyanov
2026-05-16 11:10:13 +06:00
parent b5ee98357d
commit dcb41ce001
@@ -151,14 +151,6 @@ Documents/UserProfile/
---
## Тест-результаты (2026-05-16)
- ClaudeServiceTests: 4/4
- CrisisDetectorTests: 17/17 (включая RU+EN, нормализация)
- ProfileManagerTests: 6/6 (включая onboarding init)
- SessionSchedulerTests: 3/3
- **ИТОГО: 30/30, 0 failures**
## App Lock (Face ID / Touch ID / Passcode)
**Файлы:**
@@ -172,3 +164,73 @@ Documents/UserProfile/
- При уходе в фон (`scenePhase == .background`) — блокируется
- При возврате — LockView показывается поверх всего, сразу запрашивает биометрию
- Симулятор: биометрия эмулируется через Features → Face ID → Enrolled
---
## Голосовой ввод
**`Services/VoiceInputService.swift`** — `@MainActor ObservableObject`:
- `AVAudioEngine` + `SFSpeechRecognizer` (locale: ru-RU с fallback на системный)
- Push-to-talk: `startRecording()` / `stopRecording()`
- `onTranscript: ((String) -> Void)?` — коллбэк с финальным текстом
- `audioLevel: Float` — уровень звука в реальном времени (→ орб анимация)
- `requestPermissions()` — запрашивает mic + speech recognition
---
## Адаптивное расписание (ScheduleNegotiationService)
**`Services/ScheduleNegotiationService.swift`**:
- `nextSessionDate` — следующая запланированная сессия (UserDefaults)
- `buildSuggestion()` → предлагает время на основе паттерна прошлых встреч
- `acceptSchedule(date)` → сохраняет и ставит разовое `UNCalendarNotificationTrigger`
- `postpone(by: PostponeOption)` → переносит на +1ч / +3ч / завтра / skip
- Уведомление содержит action-кнопки прямо из шторы (без открытия приложения)
**Флоу в конце сессии:**
1. Агент завершает сессию → `SessionManager.endSession()``clearSchedule()`
2. `SessionViewModel.endSession()` → показывает `CardData` с предложением времени
3. Пользователь: "Да, подходит" / "Другое время" / "Без расписания"
4. При выборе времени → `ScheduleNegotiationService.acceptSchedule(date)` → уведомление
**HomeView:**
- Если есть расписание → показывает badge "Следующая: пятница 20:00" + кнопка "Перенести"
- Если нет расписания → "Назначить следующую встречу" (кнопка открывает `PostponeSheetView`)
---
## Тулинг агента (AnalystBot)
Аналитик использует tool-use loop (`ClaudeService.completeWithTools`).
**4 инструмента:**
| Tool | Описание |
|------|----------|
| `get_index` | Индекс сессий — таблица дат/тем/тегов, < 1K токенов |
| `search_sessions` | Полнотекстовый поиск по архиву |
| `read_session` | Прочитать полную сессию по дате |
| `read_profile` | Прочитать profile.md |
Агент сам решает когда обращаться к хранилищу — когда видит паттерн или нужен контекст прошлых встреч.
---
## Session Index
**`ProfileManager.updateSessionIndex()`** обновляет `sessions/index.md`:
```
| Дата | Темы | Теги | Содержание |
|------------|------------------------|-------------------|-------------------|
| 2026-05-16 | работа, усталость | #сессия #инсайт | Говорит что устал |
```
Заполняется автоматически при `endSession()`. Агент читает через `get_index` — без засорения контекста полными файлами.
---
## Тест-результаты (2026-05-16)
- ClaudeServiceTests: 4/4
- CrisisDetectorTests: 17/17 (включая RU+EN, нормализация)
- ProfileManagerTests: 6/6 (включая onboarding init)
- SessionSchedulerTests: 3/3
- **ИТОГО: 30/30, 0 failures**