simbiot-harness/docs/events-meta-audit-2026-10-15.md

92 lines
7.1 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.

# Аудит мета-информации в событиях (t-261015083454, принцип m-516174369)
Дата: 2026-10-15. Стор: ~2.8M событий. Принцип Alex: **события должны
сохраняться с максимумом мета-информации** — событие без контекста теряет
ценность при разбирательстве инцидентов и аналитике burn/AUM.
## 1. Системные поля (у всех событий, таблица `events`)
| Поле | Есть | Оценка |
|---|---|---|
| `id`, `timestamp` (UTC ISO), `version` | ✅ | ок |
| `aggregate` / `aggregate_id` | ✅ | ок, но двойная кодировка меты (см. §3) |
| `sig` / `key_id` / `prev_sig` (ed25519-цепочка) | ✅ | криптоаудит t-260930083716 |
| `trace_id`, `level`, `источник`, `context` | ❌ в payload | точечно, неравномерно |
## 2. Аудит payload по типам (выборка последних 150 на тип)
| Тип (кол-во) | trace_id | level | ts | источник | прочая мета |
|---|---|---|---|---|---|
| `CycleTicked` (1.35M) | — | ✅ agg_id | — | — | seq |
| `ReflexObserved` (1.33M) | — | ✅ agg_id | ✅ | — | load1 |
| `ToolCalled` (34.7k) | **❌** | **❌** | **❌** | — | tool, input |
| `ToolResult` (34.7k) | **❌** | **❌** | **❌** | — | tool=**«?»-заглушка**, result |
| `BudgetSpent` (28.6k) | ✅ | ✅ | — | ✅ | model, tokens |
| `DigestWritten` (21.3k) | — (summary_ref) | ✅ | — | stub-флаг | period, text |
| `InvocationStarted` (1.4k) | ✅ | ❌ | ✅ | — | model |
| `TaskSubmitted` (230) | — | — | — | ✅ source | id, size, est_minutes |
| `TaskClaimed` (434) | — | ✅ | — | — | session_id |
| `TaskCompleted` (317) | — (result_ref) | **❌** | — | — | answer |
| `TaskFailed` (12) | — | ×2/12 | — | ×1/12 | error |
| `EscalationRaised` (96) | — | ✅ from/to | — | ✅ source | severity, task_id, context |
| `MessageReceived` (1238) | — | — | ✅ date | ✅ username | 19 полей, эталон |
| `MessageTranscribed` (65) | — | — | — | ✅ engine | transcript |
| `RagQueried` (412) / `PortalMcpCalled` (64) | ✅ | ✅ | ✅ ms | — | query/result_preview |
| `CycleError` (51) | — | ✅ | — | — | error, trace |
| `AumMeasured` (16) | — | — | ✅ | — | aum, burn_24h/7d, policy |
## 3. Найденные пробелы (по убыванию веса)
1. **`ToolCalled`/`ToolResult` — 68k событий без `trace_id`/`level`/`ts`**
(⅔ всех нетаймовых событий стора; связь с тиком только через
декодирование `aggregate_id = "<level>-<seq>:<n>"`). У `ToolResult`
имя инструмента — заглушка `"?"` (после параллельных вызовов вообще
непонятно, чей результат).
2. **`TaskCompleted`/`TaskFailed` без `level`** — не видно, какой уровень
лестницы закрыл/уронил задачу; `trace_id` только как `result_ref`.
3. `DigestWritten.summary_ref` ≠ trace_id напрямую — это trace_id тика,
но имя не говорит об этом (путаница при разборе инцидентов).
4. `BudgetSpent` без `ts` (после миграции v2 на инкрементальные записи —
только `timestamp` колонки; хронология внутри тика не видна).
5. Двойная кодировка: `level` дублируется в `aggregate_id` и payload —
данные об оси «уровень» живут в двух местах с разной полнотой.
## 4. Внедрено в этом тике (коммит f3ab66e)
- **`harness/runtime.py` `_wire_trace_hooks`**: `trace_id`, `ts`, `level`
теперь в каждом trace-событии (`InvocationStarted`/`ToolCalled`/
`ToolResult`); `ToolResult` дополнительно `duration_ms` (из
`AfterToolCallEvent.duration`), `ok: bool`, `exception` (до 500с),
имя инструмента из `tool_use` (заглушка `"?"` убрана).
- **`harness/_llm_worker.py`**: проброс `level` в `_wire_trace_hooks`.
- **`harness/scheduler.py`**: `TaskCompleted`/`TaskFailed` получают
`level` + `trace_id` тика-воркера.
- Проверено: смоук-скрипт (мета во всех 4 типах), 5 смежных тестов PASS
(task_batch 11, timeout_kill 2, ttft_retry, tool_budget, task_claim_race).
Прирост мета-покрытия: trace-события (доля LLM-активности без мета-
контекста) — с **0% → 100%** новых событий; TaskCompleted/TaskFailed —
с 0% → 100% `level`.
## 5. План на следующие итерации (не внедрено — вне бюджета тика)
| # | Что | Зачем | Где |
|---|---|---|---|
| 1 | `ts` в `BudgetSpent` (воркер уже пишет после каждого вызова) | хронология spend внутри тика, детект всплесков burn | `_llm_worker._emit_budget_incremental` |
| 2 | `trace_id` в `DigestWritten` (рядом с `summary_ref`) и переименование семантики `summary_ref` в доках | единая ось «тик → трасса → spend» | `scheduler.py` |
| 3 | `source` (`cli`/`poller`/`scheduler`/`daemon`) в `TaskClaimed`, `MessageSeen`, `ReplySent` | отличать ручные команды от автоматических | `scheduler.py`, `commands.py` |
| 4 | `host`/`pid`/`commit` в `InvocationStarted` (или в `CycleTicked` раз в тик) | мульти-инстансность: кто именно писал (инцидент rogue-key t-261008084600) | `runtime.py` |
| 5 | `duration_ms` в `CycleTicked`/`DigestWritten` | находить медленные тики без парсинга логов | `scheduler.py` |
| 6 | Унификация: helper `es.meta(level=…)` для единообразной меты во всех `append_event` | убрать ручную возню, единый контракт | `es.py` |
Ретро-заполнение старых событий **не делаем**: стор append-only + подписи
ed25519 — перезапись сломает тампер-цепочку. Граница: события до
f3ab66e — «до мета-стандарта», после — полные.
## 6. AUM-фильтр
Аудит меты — инвестиция в долгосрочную базу: разбор инцидентов (часы
диагностики → минуты по SQL-запросу), честный burn-контроль 9router
(193.68 у.е./7д — прямой минус AUM), доверие ко стору у внешних
проверяющих (подписи + мета =аудито-готовность). Слабого короткого дохода
нет — чистый плюс в базу.