Files
microdao-daarion/docs/HUMANIZED_STEPAN_v2.7_CHANGELOG.md
Apple 67225a39fa docs(platform): add policy configs, runbooks, ops scripts and platform documentation
Config policies (16 files): alert_routing, architecture_pressure, backlog,
cost_weights, data_governance, incident_escalation, incident_intelligence,
network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix,
release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout

Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard,
deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice,
cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule),
task_registry, voice alerts/ha/latency/policy

Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks,
NODA1/NODA2 status and setup, audit index and traces, backlog, incident,
supervisor, tools, voice, opencode, release, risk, aistalk, spacebot

Made-with: Cursor
2026-03-03 07:14:53 -08:00

148 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Humanized Stepan — CHANGELOG v2.7
**Version:** v2.7
**Date:** 2026-02-25
**Базується на:** v2.6 (Jaccard guard, tone_constraints, 3-рівневі привітання, seeded RNG)
---
## Summary
- Додано **memory horizon**: `recent_topics` (до 5 записів) замість єдиного `last_topic`.
- Додано **human topic labels** (`last_topic_label`) — Степан оперує "план на завтра поле 12", а не "plan_day".
- Додано **`summarize_topic_label()`** — rule-based витяг 68 слів з тексту без дієслів-тригерів і стоп-слів.
- Light follow-up (≤6 слів + last_topic) **не додає шум** до `recent_topics` (`depth="light"``push` не відбувається).
- Contextual greeting (`interaction_count ≥ 8`) тепер: з ймовірністю 20% (seeded rng) підхоплює `recent_topics[-2]` — Степан "пам'ятає" більше однієї теми без подвійного згадування.
- **ZZR safety disclaimer**: якщо погодний тригер + обприскування/гербіцид/ЗЗР — автоматично додається `"Дозування та вікна застосування — за етикеткою препарату та регламентом."`.
- Додано **`tests/test_stepan_invariants.py`** — 25 тестів-інваріантів проти "повзучої ботячості".
---
## Key features (деталі)
### Memory horizon — `recent_topics`
```json
"recent_topics": [
{"label": "план на завтра поле 12", "intent": "plan_day", "ts": "2026-02-25T..."},
{"label": "датчики вологості поле 7", "intent": "iot_sensors", "ts": "2026-02-25T..."}
]
```
- Максимум 5 записів; старіші витісняються.
- `last_topic` і `last_topic_label` — backward-compat aliases на `recent_topics[-1]`.
- Dedup: якщо той самий `intent` + `label` підряд — не дублюється.
### summarize_topic_label
| Вхід | Вихід |
|---|---|
| `"зроби план на завтра по полю 12"` | `"План на завтра по полю 12"` |
| `"перевір датчики вологості поле 7"` | `"Датчики вологості поле 7"` |
| `"сплануй тижневий збір по полях"` | `"Тижневий збір по полях"` |
Правила: прибирається leading action verb (зроби/перевір/порахуй/…), стоп-слова, обрізка до 8 слів. Числа, поля, культури, дати зберігаються.
### ZZR disclaimer
Regex `_ZZR_RE` спрацьовує на: `обробк|обприскування|гербіцид|фунгіцид|ЗЗР|пестицид|інсектицид|протруювач`.
Застереження додається лише коли є **і** погодний тригер **і** ZZR-тригер в одному повідомленні.
### Invariant tests (anti-regression)
| Інваріант | Обмеження |
|---|---|
| INV-1: Greeting | ≤ 80 символів |
| INV-2: Thanks/Ack | ≤ 40 символів |
| INV-3: Заборонені фрази | "чим можу допомогти", "оберіть", "я як агент", "я бот" |
| INV-4: Технічні слова | container, uvicorn, trace_id, STEPAN_IMPORTS_OK |
| INV-5: ZZR disclaimer | при ZZR+погода → "за етикеткою" або "за регламентом" |
| INV-6: Horizon | `len(recent_topics) ≤ 5` після 7+ push |
| INV-7: Міграція | lazy, idempotent, backward-compat |
---
## Backward compatibility
| Аспект | Деталі |
|---|---|
| `_version` | 3 → 4 (нові поля `recent_topics`, `last_topic_label`) |
| Міграція | Lazy при `load_user_profile()` — виконується автоматично при першому зверненні |
| `last_topic` | Залишається як alias, завжди синхронізований з `recent_topics[-1].intent` |
| `last_topic_label` | Новий alias на `recent_topics[-1].label`; якщо нема — встановлюється під час міграції |
| `tone_constraints` | Вже в v2.6; міграція додає якщо відсутній |
| `update_profile_if_needed` | Новий параметр `depth="deep"` (default) — backward-compat, старі виклики не ламаються |
| `recent_topics` відсутній | Якщо профіль v3 без `recent_topics``migrate_profile_topics()` створює 1 елемент з `last_topic` |
Міграція `migrate_profile_topics()`**idempotent**: повторний виклик не змінює вже мігрований профіль.
---
## Non-goals / not included
- Немає LLM у light mode або reflection.
- Немає змін в інфраструктурі (Dockerfile, compose, env).
- Немає змін у Gateway/http_api.py.
- Немає нових API ендпоінтів.
- Немає змін у поведінці deep mode orchestration.
- Немає змін у системному промпті (тільки хедер-версія).
---
## Tests
**Результат:** 101/101 зелених (без регресій з v2.6)
| Файл | Тестів | Опис |
|---|---|---|
| `tests/test_stepan_invariants.py` | 25 | Нові інваріанти anti-regression |
| `tests/test_stepan_acceptance.py` | 28 | Acceptance + v2.7 сесійні сценарії |
| `tests/test_stepan_light_reply.py` | ~26 | Light reply юніт-тести |
| `tests/test_stepan_memory_followup.py` | ~22 | Memory + follow-up класифікація |
```bash
# Тільки інваріанти
python3 -m pytest tests/test_stepan_invariants.py -v
# Acceptance
python3 -m pytest tests/test_stepan_acceptance.py -v
# Всі Stepan тести
python3 -m pytest tests/test_stepan_invariants.py tests/test_stepan_acceptance.py \
tests/test_stepan_light_reply.py tests/test_stepan_memory_followup.py -v
```
---
## Known limitations
### Timezone і daily seed
`date.today()` використовує локаль контейнера. Контейнер має бути в `Europe/Kyiv` (`TZ=Europe/Kyiv`), інакше "новий день" Степана настане о 22:00 або 23:00 за Київським часом. Перевірка:
```bash
docker exec dagi-gateway-node1 date
```
### Memory-service downtime
При недоступності — деградація до локального in-memory кешу (TTL 30 хв). Кеш не переживає рестарт контейнера. Профілі не зберігаються між сесіями якщо memory-service down > 30 хв.
### ZZR regex — можливий overreach
Слово `"обробка"` без агрохімічного контексту (напр. "обробка ґрунту") може спрацювати. Якщо в проді виявиться шум — звузити regex: вимагати ще одне слово з `[препарат|норма|л/га|кг/га|концентрат]`.
---
## Rollback
```bash
# Відкатити зміни у конкретних файлах
git checkout HEAD~1 -- crews/agromatrix_crew/memory_manager.py
git checkout HEAD~1 -- crews/agromatrix_crew/light_reply.py
git checkout HEAD~1 -- crews/agromatrix_crew/run.py
# Rebuild gateway (без секретів)
cd /opt/microdao-daarion
docker compose -f docker-compose.node1.yml up -d --build dagi-gateway-node1
# Перевірка
docker logs dagi-gateway-node1 --since 5m 2>&1 | grep -E "Stepan mode|STEPAN_IMPORTS_OK|error|Error" | tail -30
```