92 lines
7.1 KiB
Markdown
92 lines
7.1 KiB
Markdown
# Аудит мета-информации в событиях (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), доверие ко стору у внешних
|
||
проверяющих (подписи + мета =аудито-готовность). Слабого короткого дохода
|
||
нет — чистый плюс в базу.
|