[2026-05-16] reflect-app: voice, scheduling, agent tools, session index docs
This commit is contained in:
@@ -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**
|
||||
|
||||
Reference in New Issue
Block a user