Files
microdao-daarion/docs/HUMANIZED_STEPAN_v2.8_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

124 lines
5.0 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.8
**Version:** v2.8
**Date:** 2026-02-25
**Базується на:** v2.7.2 (PII-safe telemetry, recent_topics horizon, invariant tests)
---
## Summary
- **Multi-user farm model**: `FarmProfile` тепер зберігається під ключем `farm_profile:agromatrix:chat:{chat_id}` — shared для всіх операторів в одному чаті.
- **UserProfile** залишається per-user (`user_profile:agromatrix:{user_id}`) — стиль, recent_topics, interaction_summary окремі для кожного.
- **Lazy migration**: перший запит з `user_id` автоматично мігрує старий legacy-ключ `farm_profile:agromatrix:{user_id}` у новий chat-ключ (write-through, без ручного втручання).
- **Conflict policy**: якщо chat-profile вже існує і відрізняється від legacy — не перезаписуємо; лише tlog `farm_profile_conflict`.
- **FarmProfile v5**: додані нові поля (`farm_name`, `field_ids`, `crop_ids`, `active_integrations`, `iot_sensors`, `alert_thresholds`, `seasonal_context`).
- **Backward-compat**: `load_farm_profile(chat_id)` без `user_id` — не крашить, повертає default.
---
## Key features (деталі)
### Нові fact-ключі
| Тип | Ключ | Scope |
|---|---|---|
| UserProfile | `user_profile:agromatrix:{user_id}` | per-user (без змін) |
| FarmProfile (v2.8) | `farm_profile:agromatrix:chat:{chat_id}` | per-chat (новий) |
| FarmProfile (legacy) | `farm_profile:agromatrix:{user_id}` | deprecated, мігрується lazy |
### Lazy Migration Flow
```
load_farm_profile(chat_id, user_id)
├── cache hit (chat-key)? → return
├── memory-service chat-key? → return + cache
├── memory-service legacy-key (user_id)?
│ ├── YES → copy to chat-key (write-through) + return migrated profile
│ │ tlog: farm_profile_migrated
│ └── NO → default farm_profile(chat_id)
```
### Conflict Policy
При явній міграції через `migrate_farm_profile_legacy_to_chat()`:
- Якщо chat-profile існує і **суттєво відрізняється** (crops/field_ids/region/season_state) → NOT overwritten
- `tlog: farm_profile_conflict reason=legacy_diff`
- Повертається існуючий chat-profile
Критерій суттєвої відмінності (`_farm_profiles_differ`): порівнює `crops`, `field_ids`, `fields`, `region`, `season_state`, `active_integrations`.
### FarmProfile v5 — нові поля
```json
{
"_version": 5,
"chat_id": "...",
"farm_name": null,
"field_ids": [],
"crop_ids": [],
"active_integrations": [],
"iot_sensors": [],
"alert_thresholds": {},
"seasonal_context": {},
"region": null,
"crops": [],
"fields": [],
"season_state": null
}
```
---
## Backward Compatibility
| Аспект | Деталі |
|---|---|
| `load_farm_profile(chat_id)` | Без `user_id` — не крашить (legacy path пропускається) |
| `load_farm_profile(chat_id, user_id)` | Новий API; `user_id` потрібен тільки для lazy migration |
| `save_farm_profile(chat_id, profile)` | API без змін (тепер під chat-key автоматично) |
| Legacy ключ | Не видаляється, існує в memory-service до явного очищення |
| `_version` FarmProfile | 1 → 5; non-breaking (нові поля, старі залишаються) |
---
## Non-goals / not included
- Немає автоматичного merge при конфлікті.
- Немає видалення legacy ключів (тільки read-migrate).
- Немає зміни light/deep логіки, тональності, банків фраз.
- Немає нових ендпоінтів або інфра-змін.
---
## Tests
**Результат:** 161/161 зелених (без регресій з v2.7.2)
| Файл | Нових тестів | Опис |
|---|---|---|
| `tests/test_stepan_v28_farm.py` | 24 | Multi-user farm: ключі, міграція, конфлікт, acceptance |
```bash
# Тільки v2.8 farm тести
python3 -m pytest tests/test_stepan_v28_farm.py -v
# Всі Stepan тести
python3 -m pytest tests/test_stepan_v28_farm.py tests/test_stepan_telemetry.py \
tests/test_stepan_invariants.py tests/test_stepan_acceptance.py \
tests/test_stepan_light_reply.py tests/test_stepan_memory_followup.py -v
```
---
## Rollback
```bash
git checkout HEAD~1 -- crews/agromatrix_crew/memory_manager.py \
crews/agromatrix_crew/run.py
docker compose -f docker-compose.node1.yml up -d --build dagi-gateway-node1
```
Після rollback до v2.7.x: farm_profile знову читатиметься зі старого legacy-ключа (якщо є в cache/memory-service). Новий chat-ключ залишиться в memory-service, але не буде використовуватись.