Перейти к основному содержимому
Перевод от 2026-10-16; оригинал с тех пор изменился.

События

В Brabo сосуществуют три семейства имён, и их легко спутать, потому что все используют предмет.глагол:

семействогде хранитсядолговечность
Доменное событиестрока в session_eventsпостоянное и неизменяемое
Broadcastканал Phoenix → браузерэфемерный, не сохраняется
Spanтрасса OpenTelemetryхранение Tempo (24 ч локально)

Только первое является контрактом. Два других — транспорт и наблюдение.

Доменное событие​

Строка в session_events, append-only, с плотным seq по сессии (RN-002). Колонки:

колонкачто
iduuid
session_idсессия-владелец
seqпорядок внутри сессии, начиная с 1, без пропусков
typeидентификатор ниже
actorкто вызвал: {kind, id} — пользователь, агент или система
payloadjsonb, собственный формат каждого типа
created_at—

type в коде — свободная string — нет ни union в TypeScript, ни enum в базе, перечисляющих допустимые типы. Список ниже извлечён из точек эмиссии и поэтому может устареть, ничего не сломав. См. примечание в конце этой страницы.

Сессия​

типкогда
session.createdсессия рождается в created
session.activatedперешла в active
session.drainingузел, на котором она размещена, дренируется
session.closedобычное завершение
session.closed_abnormallyзавершение с причиной — node_shutdown самая частая
session.reopenedсессия closed/closed_abnormally вернулась в active (ADR 0183)

Терминальная сессия больше не принимает разговор (RN-581). Когда сессия closed или closed_abnormally, запись события разговора отклоняется с 409 и reason: "sessao_encerrada". Разговор — это тип, существующий только как разговор (chat.message, chat.message_cancelled, chat.structured_question, chat.structured_question_answered, agent.status, agent.activated, handoff.offered, handoff.accepted, readiness.confirmed, necessity.validated, architecture.readiness_confirmed), или любое событие, чей актор — разговорный агент: поэтому tool.call/agent.response Креатива отклоняются, а те же типы от Психолога, который работает поверх закрытой сессии, продолжают приниматься. Человеческие решения о ожидающем действии (action.approved/action.denied) тоже продолжают приниматься: очередь действий переживает сессию. Сессия, закрытая потому, что разговор простаивал дольше потолка, несёт termination_reason: "conversation_idle_timeout" и заканчивается closed, как heartbeat_timeout.

Закрытую сессию можно открыть заново (RN-649, ADR 0183). POST /projects/:projectId/sessions/:sessionId/reopen (developer, ADR 0184) возвращает сессию closed/closed_abnormally в active и записывает session.reopened с {from, to, closedAt, terminationReason} — единственную запись об интервале, когда она была закрыта, поскольку closed_at и termination_reason в строке очищаются. Ни одно предыдущее событие не редактируется, и kind сессии не меняется. Сессия, у которой уже есть execution.activated, отклоняется с 409 sessao_com_execucao.

Чат и агенты​

типкогда
chat.messageсообщение в ленте сессии, от пользователя или агента
chat.message_queuedсообщение пришло, когда агент был посреди хода, и попало в его ОЧЕРЕДЬ, а не было отклонено (RN-673, ADR 0191). Актор: агент. Payload: mensagemId (id chat.message), texto, idioma и posicao. Текст передаётся здесь, потому что именно его очередь перечитывает после перезапуска engine. Поставленное в очередь сообщение остаётся ОЖИДАЮЩИМ, пока chat.message_delivered или chat.message_cancelled его не назовёт; не более 10 на агента и сессию
chat.message_deliveredначался ход, читающий очередь: ожидающие сообщения читаются ВМЕСТЕ, по порядку, в одном ходе. Актор: агент. Payload: mensagemIds
chat.message_cancelledтот, кто ОТПРАВИЛ ожидающее сообщение, отменил его — ни один агент его не прочитал. Актор: этот пользователь. Payload: mensagemId, agente. Записывается engine; отклоняется в закрытой сессии (RN-581)
chat.structured_questionКреатив запросил НЕСКОЛЬКО ответов сразу, через форму — инструмент ask_structured_questions (RN-162). Каждый вопрос несёт id, label, type, options и allowOther — это выход свободного текста для select, и он равен true, когда модель ничего не объявляет (RN-171)
chat.structured_question_answeredпользователь ответил на форму; ответы также возвращаются как chat.message, чтобы агент их прочитал
agent.activatedагент взял работу в сессии
agent.responseполный консолидированный ответ агента. modelName говорит, КАКАЯ модель его сгенерировала, у трёх производителей (пять разговорных агентов, ToolLoop каждого исполнительного агента/агента gate и чат api без активного агента) — null, когда ход упал до разрешения binding, и отсутствует в событиях, записанных до появления правила (RN-175). От разговорного агента content — это только ЗАКЛЮЧИТЕЛЬНЫЙ текст хода, а passos (отсутствует, когда их нет) перечисляет по порядку текст предыдущих раундов, который лента сворачивает под «Шаги хода» (RN-698, AT-395)
agent.errorсбой агента, с origem (infra/modelo/codigo/politica) и mensagem, которое он говорит в ленте (RN-059). Также выдаётся с reason: turno_interrompido_por_reinicio (источник infra), когда engine перезапустился посреди хода и осиротевший статус working закрывается при загрузке или подъёме агента, после чего идёт agent.status: idle (RN-586). Покрывает весь ход, а также сбой ОДНОГО инструмента посреди цикла, с tool и retentativa в payload (RN-163)
tool_router.decidedшаг, на котором Jev выбрал инструмент (RN-625, ADR 0179): menuAntes/menuDepois, escolha, confianca, segunda, anterior, aplicado (меню вышло меньше каталога), motivoDaQueda + origemDaQueda (infra/modelo/codigo), когда Jev упал, latenciaMs, custoMicros (РЕАЛЬНЫЙ usage.cost) и foraDoCardapio (инструменты, которые модель вызвала, хотя их не предлагали). Записывается фасадом engine для каждого агента; отсутствует, когда маршрутизатор не запрашивался (provider не OpenRouter, меньше двух инструментов, ключ workspace выключен). Измерение выигрыша (AT-239) читается из этого события и из token_usage, никогда не записывается вручную
tool.resultрезультат выполнения инструмента, записываемый hook Engine.Harness.Hooks.EventLog и, для семи разговорных агентов (Infra Lead с RN-617), их серверами с tool, ok и resultado (или erro), обрезанным до 2 000 символов с resultadoTotal, когда обрезается (RN-589). Тот же payload приходит от Infra Lead для каждого инструмента, который он выполняет напрямую, и от Dev Lead, когда приостановленный вызов разрешается — никогда пока он ждёт одобрения (RN-593)
handoff.offeredагент предложил работу другому
handoff.acceptedполучатель принял. Обычно человеком (актор user). Когда принятие подразумевалось в клике «Я готов» (RN-658), актор остаётся этим человеком, а payload — и payload следующего agent.activated — несёт также implicito: { via: "readiness.confirmed", readinessEventId }. С RN-660 (ADR 0186) предложение PO Архитектору может быть принято актором system handoff-auto-accept, и тогда payload несёт также automatico: true, emNomeDe (кто открыл сессию — репозиторий создаётся от имени этого человека) и criterio (regras, cobertas, repositorio)
handoff.auto_accept_failedсистема решила принять предложение PO Архитектору (RN-660), и принятие упало. Payload: handoffId, toAgent, origem (infra) и error. Актор system handoff-auto-accept. Предложение сохраняет кнопку, если не было помечено accepted
handoff.supersededhandoff offered перестал быть действующим и больше не может быть принят (RN-635, ADR 0182). Payload: handoffId, toAgent, motivo (agente_ativado — получатель был активирован любым путём; nova_oferta — более новое предложение тому же получателю в проекте его заменило) и substitutaId (заменившее предложение, null для agente_ativado). Записывается актором system handoff-lifecycle в сессии СТАРОГО предложения, которая может быть закрыта — это запись, а не разговор, поэтому RN-581 её пропускает. status строки становится superseded; событие — это история
context.compactedменеджер контекста резюмировал самые старые ходы истории агента, чтобы уместиться в окно. С RN-580 payload несёт, помимо tokensBefore/tokensAfter, summary, заменивший эти ходы, agent — владельца истории, и messagesSummarized. События, записанные раньше, несут только два счётчика — резюме потеряно, и регидратация говорит об этом, а не выдумывает его

Что перечитывает разговорный агент (RN-580). Когда один из семи разговорных агентов поднимается над сессией, в которой уже есть разговор, Engine.Agents.Reidratacao восстанавливает его историю из хвоста этого журнала (последние 200 событий): chat.message, agent.response, chat.structured_question (как ход самого агента, с метками и вариантами) и СОБСТВЕННЫЕ tool.call/tool.result (как текстовую заметку — события не несут id вызова, поэтому никогда не повторяются как role: tool). chat.structured_question_answered намеренно пропускается: api записывает те же ответы как chat.message сразу после, и именно это агент прочитал вживую. chat.message, отменённое в очереди или ещё ожидающее для этого агента, тоже пропускается (RN-673): первое так и не было сказано, второе придёт ходом, читающим очередь. С RN-589 все семь записывают tool.result с текстом, который вернул инструмент (resultado, обрезанный до 2 000 символов, с resultadoTotal, дающим реальный размер при обрезке); вызов сессии, записанный до этого, не имеет tool.result, и заметка говорит, что в журнале нет исхода. Когда разговор длиннее хвоста, история открывается системным сообщением о том, сколько предыдущих событий осталось за бортом, последним записанным резюме компактизации и открывающими сообщениями.

Предлагаемые действия​

типкогда
proposed_action.createdдействие родилось — до любого выполнения. payload.status говорит, как оно родилось (pending, auto_approved или denied), и именно это отличает человеческое решение от политики (RN-049). payload.reason говорит, КАКОЕ правило политики решило — строка, которую возвращает decide(), во всех трёх исходах; отсутствует в событиях, записанных до появления правила, что означает «не записано», а не «без причины». Одноимённая строка outbox его НЕ несёт (RN-567). В действиях terminal — единственном типе, чьё решение учитывает область пути, — payload.scopeRoot говорит, с КАКИМ корнем сравнивала область, как { executionMode, ancora, segmento }: container → ancora: raiz_gerenciada и workspace_dir_name; mounted → ancora: base_de_projetos и сегмент под BRABO_PROJECTS_BASE (ancora: indisponivel, segmento: null, когда папка вне базы или базы нет); runner → ancora: nome_da_pasta и workspace_dir_name. НИКОГДА абсолютный путь, который раскрыл бы $HOME пользователя каждому участнику. Отсутствует в старых событиях и в других типах действий; в outbox тоже нет (RN-609)
proposed_action.approvedрешено пользователем — actor — это тот, кто кликнул. Автоодобрение здесь НЕ проходит: оно появляется в created со status: auto_approved и актором-агентом
proposed_action.deniedотклонено — терминальное состояние. actor — кто отказал, а payload.reason — причина
proposed_action.executedвыполнено успешно
action.failedвыполнено и упало
permission.grantedразрешение записано в политику

Backlog​

типкогда
backlog.epic_created—
backlog.story_created—
backlog.story_transitionedсмена состояния истории. actor говорит, кто её продвинул: agent/po в режиме auto, user в режиме manual (RN-048)
backlog.story_completedPO дополнил существующую историю draft через complete_story — связанные правила, заполненные RF/DoD/DoR — вместо того чтобы создавать её заново (RN-720)
backlog.story_promotion_proposedPO завершил ПОЛНУЮ историю в проекте в режиме manual: она остаётся draft в ожидании решения пользователя, и ни одна её задача до тех пор не может быть взята (RN-048)
backlog.story_promotion_returnedпользователь ОТКЛОНИЛ продвижение и вернул историю PO с причиной — которая становится закреплённым сообщением в его сессии, как gate, возвращённый dev (RN-048)
backlog.story_updatedзаголовок и/или описание истории draft без задачи в работе исправлены пользователем (вкладка Backlog) или PO (update_story). Несёт previousTitle, title и descriptionChanged (RN-727)
backlog.story_archivedистория draft без задачи в работе АРХИВИРОВАНА пользователем или PO (archive_story): она и её задачи уходят из backlog, покрытия, плана и claim; строка остаётся. Несёт reason и taskIds (RN-727, ADR 0212)
backlog.story_demotedмодуль исчез из module_map; история вернулась в draft (RN-012)
backlog.story_overlap_warnedистория создана, но ВСЕ правила, которые она упоминает, уже покрыты другой — предупреждение, не блокировка: судит о наложении пользователь (RN-081)
backlog.semantic_duplicate_warnedзаписана история или бизнес-правило, чей ЗАГОЛОВОК по embedding находится на пороге или выше относительно существующего того же типа в проекте — предупреждение, никогда отказ; payload называет похожий элемент и косинус. Актор system/duplicata-semantica (RN-681)
backlog.semantic_duplicate_check_skippedпроверка семантического дубликата НЕ смогла выполниться — нет provider embedding, daemon недоступен, потолок 10 с — и reason говорит, что именно; элемент всё равно записан (RN-681)
backlog.story_modules_assignedсвязь история ↔ модуль
backlog.task_created—
backlog.task_claimeddev agent взял задачу
backlog.task_status_changed—
backlog.task_merge_conflictодобренный merge PR задачи отклонён из-за конфликта слияния: taskId, pullRequestId, conflictingFiles, actionId. С RN-715 задача возвращается в in_progress, а dev agent-владелец пробуждается строкой task.merge_conflict в outbox (RN-705)
backlog.task_blockedисчерпан потолок попыток исправления, или зарегистрировано препятствие
backlog.task_unblocked—
backlog.epic_without_storyPO закончил ход, создав эпик и НИ ОДНОЙ истории для него. Эпик не порождает задачу — порождает история, — поэтому это состояние, которое блокирует выполнение без видимой ошибки. Явный исход по образцу RN-059: долговечное событие с origem, epicIds/epicTitles и сообщением, плюс broadcast agent.error. Сообщается ОДИН раз за случай, никогда в цикле (RN-165)
backlog.handoff_not_offeredPO закончил ход, когда все бизнес-правила покрыты, но не смог предложить handoff Архитектору: у какой-то истории нет задачи (origem: modelo, с storyIds/storyTitles), или чтение backlog либо создание предложения упало (origem: infra). Когда у каждой истории есть задача, сервер PO сам предлагает handoff (RN-700)

Выполнение и gates​

типкогда
execution.plan_proposedВЫВЕДЕН ИЗ ОБИХОДА с ADR 0086 (RN-284) — в старых сессиях этот тип ещё может быть в журнале; новые сессии используют proposed_action типа propose_execution_plan (см. docs/reference/permissions.md), потому что план Dev Lead стал настоящим решением, одобряемым или отклоняемым в Одобрениях, а не простым событием
execution.activatedначалась фаза выполнения. Входит только в сессию criativa — в consultiva запись отвечает 409 (RN-097). Именно это событие, а не колонка sessions.kind, говорит, ВЫПОЛНЯЕТСЯ ли сессия
execution.parallelization_suggestedсистема предложила распараллелить — выдаётся при активации, только когда у проекта есть зарегистрированный контейнер running (иначе dev agents блокируются, dev.blocked_by_container, и больше агентов лишь умножили бы заблокированных; AT-104)
execution.plan_appliedчеловек ОДОБРИЛ propose_execution_plan Dev Lead (или он был автоодобрен), и это одобрение АКТИВИРОВАЛО выполнение: каждая задача плана получила свой модуль, и ActivateExecutionUseCase отработал (RN-677, RN-678). Payload: actionId, sessaoDeExecucao, modulos, tarefasAtribuidas и — когда план несёт tarefas — tarefasPorModulo и modulosSemTarefa (модули, оставшиеся без агента, RN-709). Записывается в сессии Dev Lead, актор system/action-executor
execution.plan_failedодобренный план НЕ активировал выполнение — план больше не совпадает с действующим module_map, или активация отказала (например, 409 без репозитория). Payload: те же поля плюс motivo, фраза самой api. Человеческое решение остаётся записанным; в задачи ничего не записано, когда отклонён сам план
execution.parallelization_acceptedпринято — субагент наследует потолок базового агента
dev.starteddev agent начал цикл (активация, распараллеливание — НЕ регидратация, которая никогда не перезапускает)
dev.workingвзял задачу и собрал worktree
dev.idleочередь модуля пуста — сейчас нет задачи, которую можно взять
dev.blocked_by_containerагент НЕ взял задачу, потому что у проекта нет ЗАРЕГИСТРИРОВАННОГО контейнера running (RN-502). Он останавливается в :idle, как два выше — idle единственное состояние, которое wake ещё спасает, — и это событие единственное, что отличает «нет контейнера» от «очередь пуста» (dev.idle) и от «claim упал» (dev.error). Api никогда не вызывается: охрана выполняется ДО claim_task/1, так что ни одна задача не остаётся взятой без живого владельца. Разрешается само: container.running в outbox пробуждает каждого агента :idle проекта
dev.awaiting_approvalдействия git остались в ожидании одобрения (Фаза 12e): gate НЕ открывается — без PR нечего судить — и worktree удерживается до task.pr_settled (RN-050)
dev.awaiting_gatePR открыт, ждёт gate (Фаза 12b) — task_id/worktree остаются удержанными
dev.blockedзадача возвращена с диагнозом (лимит итераций, превышен бюджет, report_blocked, сбой worktree/контекста). С RN-743 несёт trabalhoPreservado ({branch, commit} или null): незакоммиченная работа закоммичена в ветку задачи как <agente>[bot], и следующая задача агента стартует от этой ветки
dev.idle_trippedпредохранитель сработал (RN-047) — N заблокированных задач подряд останавливают агента
dev.credit_exhaustedprovider модели отказал из-за нехватки кредита (RN-726) — агент встаёт на паузу в idle_tripped, не засчитываясь предохранителю и не беря следующую задачу; Перевзвести возобновляет
dev.rearmedпользователь перевзвёл застрявшего агента (Фаза 12b) — actor — это ПОЛЬЗОВАТЕЛЬ, который кликнул, а не агент
pr.gate_changedPR перешёл к новому gate (awaiting_qa → awaiting_secops → awaiting_user)
infra.gate_changedgate Infra
gate.rescue_parkedGateRescuer ПРИПАРКОВАЛ цикл QA/SecOps, простаивающий более 2 ч, вместо того чтобы перезапустить его (RN-722, ADR 0207); лента показывает кнопку «Возобновить gate» (RN-724). Payload: taskId, gate, idadeSegundos, motivo. Актор system/gate-rescuer
gate.interruptedпри ЗАГРУЗКЕ engine у недавнего цикла gate in_progress не было живого процесса ни на одном узле кластера: перезапуск его убил, и спасатель перезапускает его сразу, не дожидаясь порога в 15 минут (RN-823). Payload: taskId, gate, ultimaAtividadeEm, retomadoEm. Актор system/gate-rescuer; лента показывает его как предупреждение. В граф не проецируется
infra.artifact_blockedартефакт Infra отклонён

Делегирование (Фаза 8b, ADR 0038)​

типкогда
delegation.completedподспециальность завершила работу; payload.parecerArtifactId ссылается на её ВНУТРЕННИЙ artifact.qa_verdict — никогда на то, что доходит до gate
delegation.failedподспециальность не завершила работу; payload.failureOrigin — это ИСТОЧНИК (infra|modelo|codigo|politica, никогда методом исключения — ADR 0020)
delegation.dispensedlead решил НЕ делегировать; payload.justification объясняет почему — отказ от делегирования никогда не бывает молчаливым

Все три выдаются QaLeadServer, по одному на подспециальность, ОТДЕЛЬНО от вызова record_gate_verdict — событие pr.gate_changed выше остаётся единственным, описывающим сам gate; эти описывают область за ним.

Цикл инструментов​

типкогда
toolloop.limit_reachedцикл упёрся в потолок итераций. payload несёт iteration и max_iterations — потолок задаётся по ТИПУ агента (RN-085)
toolloop.budget_exceededбюджет токенов этого цикла закончился раньше работы; payload несёт tokens_spent_micros и token_budget_micros

Выдаются Engine.Harness.ToolLoop и — начиная с RN-166 — также PoServer, у которого СОБСТВЕННЫЙ цикл и который до тех пор исчерпывал потолок молча. Тот же тип и тот же payload намеренно: это тот же факт, и читающий журнал не должен учить второе имя только потому, что разговорный агент не использует ToolLoop.

Артефакты​

типсхема
artifact.product_brieftitle, summary, rules
artifact.business_ruletitle, description, origin
artifact.decision_recordcontext, options, choice, consequences — «сжатый ADR», который может выдать любой из шести разговорных агентов; переиспользует общий шаблон вместо выделенного и сосуществует с open_adr_pr (только Архитектор, документ, по-настоящему закоммиченный) (RN-505)
artifact.module_mapкарта модулей Архитектора
artifact.module_routingобраз-кандидат Архитектора по модулю, по одному элементу на модуль действующего module_map — Архитектор ПРЕДЛАГАЕТ, Infra ВЫБИРАЕТ (RN-487, ADR 0131)
artifact.module_contractsконтракт между модулями от Архитектора: по модулю — что он ВЫСТАВЛЯЕТ (modulo, expoe: [{tipo, assinatura, descricao}]), с version — каждый раз весь список, действующий заменяет предыдущий; что модуль потребляет — это dependsOn из module_map (RN-684, ADR 0200)
artifact.project_imageimage, rationale, network, resources, version (кто решил — актор: arquiteto или infra-lead) — образ контейнера проекта, выдаваемый api (DecidirImagemDoProjetoUseCase), когда его решает Архитектор или Infra Lead выбирает кандидата (RN-491); версионируется, без таблицы. Engine только ЧИТАЕТ, существует ли он, чтобы локально отклонить container_start_via_runner без него (RN-610)
artifact.insight—
artifact.prototipo_navegavelpersonas, jornadas, prototipo (telas, anotacoes), resumo — прототип UX Designer (RN-286, ADR 0087)
artifact.rfc_staff— (валидируется в Engine.Agents.StaffTools, а не ArtifactSchemas — тот же случай, что artifact.insight): problema, opcoes (список descricao/tradeoffs), recomendacao, poc (escopo, фиксированное descartavel: true). RFC от Staff (ADR 0088), возвращаемая Архитектору через handoff в том же вызове инструмента
artifact.plano_de_testestoryId, taskId, planoDeTeste, criteriosExecutaveis, estrategiaDeAutomacao — результат qa-стратегии (ADR 0090), написанный ПОСЛЕ сдачи dev и потребляемый циклом qa-verificada с ADR 0192 (RN-674)
artifact.threat_modelstoryId, threatModel, requisitosDeSeguranca — «второй момент» SecOps над ДИЗАЙНОМ истории (RN-360, ADR 0090)

Схемы закрыты: отсутствующее поле отклоняет эмиссию (Engine.Harness.ArtifactSchemas).

Архитектура и готовность​

типкогда
architecture.readiness_confirmed—
readiness.confirmedпользователь кликнул «Я готов — потребность подтверждена» с Креативом. С ADR 0185 payload несёт necessidadeValidada: true и aceiteImplicitoDoPo: true — метку, которую читает неявное принятие PO (RN-658); более старые события несут {}
necessity.validatedgate necessidade-validada (Креатив → PO): человек — никогда не вывод модели — заявляет, что бизнес-потребность, консолидированная Креативом, верна. С ADR 0185 записывается ТЕМ ЖЕ кликом, что и readiness.confirmed, как только engine принимает ход, с productBriefId: null (brief приходит из этого хода), via: "readiness.confirmed" и readinessEventId (RN-657). События отдельного клика из ADR 0095 (RN-406) несут productBriefId, указывающий на подтверждённый artifact.product_brief

Git и bootstrap​

типкогда
project.git_connectedучётные данные git привязаны к проекту
project.repository_provisionedрепозиторий создан Brabo
project.repository_adoptedрепозиторий, который уже существовал, стал принадлежать проекту (RN-046)
bootstrap.repository_adoptedтот же факт в выделенной сессии, с defaultBranch, наблюдаемой у provider
bootstrap.step_startedначался один из шести шагов Gitflow
bootstrap.step_completedзавершён
bootstrap.step_skippedуже было сделано — это успех, а не ошибка (RN-029)
bootstrap.step_degradedзавершён без одной из возможностей provider (например, защита ветки в Local)
bootstrap.step_failedупал; bootstrap можно возобновить с этой точки
bootstrap.plan_approvedпользователь одобрил план принятия — только начиная отсюда bootstrap выполняется в принятом репозитории (RN-045)
bootstrap.adopted_as_isпользователь отказался от bootstrap; ни один шаг не выполнялся, и план остаётся доказательством того, что не было применено

Стоимость​

типкогда
budget.threshold_crossed70%, 90% или 100% — один раз на порог (RN-018)

Телеметрия RAG (RN-479/480/481)​

Эти два — повествование, никогда не источник измерения, и существуют только при наличии сессии — то есть на пути агента. Поиск из вкладки RAG — это поиск проекта, и сессии у него нет, а session_events.session_id — NOT NULL, так что измерение по event log молча потеряло бы именно те поиски, которые человек сделал, глядя на оценки. Источник измерения — пара таблиц rag_searches/rag_feedback (читается pnpm --filter api medir:rag); событие лишь помещает тот же факт на временную шкалу сессии.

типкогда
rag.searchагент выполнил гибридный поиск внутри сессии — payload несёт searchId строки телеметрии, запрос, topK, сколько результатов прошло порог, была ли поиск degraded и ids chunks (RN-479, RN-481)
rag.feedbackагент оценил извлечённый chunk как util/irrelevante — payload несёт searchId, chunkId, вердикт и позицию, которую этот chunk занимал в том поиске (RN-480)

Локальный runner (ADR 0103/0104)​

типкогда
project.workspace_verifiedbrabo-runner подключился и подтвердил путь проекта с execution_mode: runner — runner является источником истины для пути, перезаписывая введённое при создании (RN-423)

Психолог​

типкогда
psychologist.analysis_completed—
psychologist.analysis_failedс классифицированной причиной: infra, modelo, código или política
psychologist.analysis_skippedв сессии не было АНАЛИЗИРУЕМОГО события, и анализ не выполнялся — payload.analisaveis и payload.eventCount показывают разницу (RN-079)
psychologist.hypothesis_proposedгипотеза с действительными evidenceEventIds (RN-021)
psychologist.hypothesis_accepted—
psychologist.hypothesis_dismissed—
psychologist.hypothesis_accepted_for_anamneseпринята и передана — звено, замыкающее цикл с Анамнезом

Анамнез и инструкции​

типкогда
anamnese.run_completed—
anamnese.run_failed—
anamnese.run_skippedраунд завершился БЕЗ профиля, намеренно — payload.motivo говорит почему (RN-063)
anamnese.analysisтекст, который модель Анамнеза написала во время раунда (payload.content); никогда не отрисовывается в ленте сессии (RN-695)
anamnese.profile_updatedproficiency_profile изменился
anamnese.agent_deviationотклонение АГЕНТА, замеченное Анамнезом (цикл, отменено пользователем, исправлено пользователем) — сигнал продукта, никогда не черта пользователя; payload — только agente, tipo и evidenceEventIds, без персональных данных, в граф не проецируется (RN-717, ADR 0205)
instruction.rolled_backоткат версии инструкции — создаёт новую версию, не удаляет (RN-027)

Broadcast​

Сообщения канала Phoenix в браузер. Они не сохраняются: кто перезагружает страницу, не получает их обратно — получает обратно event log.

broadcastчто
agent.deltaфрагмент текста потоковой передачи модели
agent.statusвидимое изменение состояния агента
agent.doneход завершился
agent.errorход упал
event.appendedновое событие вошло в журнал — триггер обновления панели; несёт только type и actorId

Доменное событие почти всегда производит event.appended; обратное неверно. С RN-579 engine выдаёт его для каждой записи, которую api подтвердила через фасад EngineApiClient (записи, предлагаемые действия, handoffs, backlog PO), и никогда для отклонённой. Записи, которые api делает сама — человек, решающий действие, переход сессии, — доходят до того же broadcast с AT-157: api просит его у engine после commit записи (POST /internal/sessions/:id/event-appended) и не просит для записей, пришедших от engine, который их уже объявляет. Браузер использует его только как триггер: инвалидирует то, что затрагивает type (события и бюджет всегда; действия, handoffs или backlog по префиксу), с минимальным окном на цель, и при живом канале опросы экрана сессии падают до 15 с (30 с для бюджета).

Кто может слушать (RN-108)​

Вход в канал session:<id> — а значит, получение любого из этих broadcasts — требует непрозрачного одноразового тикета, выдаваемого POST /projects/:projectId/sessions/:sessionId/socket-ticket (TTL 30 с). До RN-108 connect/3 сокета Phoenix не проверял ничего, кроме существования session_id: кто узнал UUID, мог войти и слушать всё. Тикет не сохраняется и не читается в event log — он живёт в session_socket_tickets, проверяется и потребляется самим engine, — поэтому не появляется в инвентаре доменных событий ниже. См. RN-108.

Span​

Имена spans OpenTelemetry. Сессия — это корневая трасса, проходящая через api и engine (ADR 0026).

Доменные имена​

Названы вручную, по одному на важную операцию. Именно их ищут в Tempo:

spanгде
session.createapi — корень
agent.turnengine — один проход ToolLoop
llm.turnengine — вызов модели
tool.callengine — выполнение инструмента
gate.scannerengine — сканер SecOps, с именем сканера в атрибуте
outbox.session_lifecycleengine — job Oban, привязанный к трассе сессии
outbox.psychologistengine — то же, анализ Психолога

Имена, производные от кода​

Декоратор @Traced в api (ADR 0035) называет span как Classe.metodo — например TransitionSessionUseCase.execute, DrizzleOutboxRepository.append. Они не помещаются в список здесь: рождаются и умирают вместе с кодом, и список устарел бы при первом переименовании.

Различие важно при запросе: доменное имя стабильно и может идти в сохранённый запрос или dashboard; имя, производное от кода, — нет.

Атрибуты, которые несут эти spans, — brabo.layer, code.namespace, code.function — служат для поиска в Tempo и не являются контрактом, в отличие от trace_id. Их можно переименовать, ничего не сломав вне Tempo.

Как перейти от сессии к tool.call, описано в runbook; вся модель описана в наблюдаемости.


Как событие доходит до engine​

Не через внешнюю очередь. Api записывает событие и намерение его опубликовать в одной транзакции (transactional outbox); Oban потребляет прямо из Postgres. Именно это предотвращает «событие записано, но engine так и не узнал».


Полный инвентарь​

Разделы выше говорят, когда происходит каждое событие. Это механический обход точек эмиссии, повторяемый при каждом pnpm docs:generate, — именно он заставляет новый идентификатор появиться здесь, даже если о нём никто не написал.

⚠️ Блок сгенерирован pnpm docs:generate. Не редактируйте вручную — следующая сборка его перезапишет.

Извлечено из точек генерации идентификаторов: 115, из них не описаны выше: 3.

  • action.failed (apps/api/src/application/use-cases/actions/execute-git-action.use-case.ts)
  • agent.activated (apps/api/src/application/use-cases/agents/activate-agent.use-case.ts)
  • agent.delta (apps/engine/lib/engine/agents/arquiteto_server.ex)
  • agent.done (apps/engine/lib/engine/agents/turno_assincrono.ex)
  • agent.error (apps/api/src/application/use-cases/agents/aceite-implicito-do-po.use-case.ts)
  • agent.plan (apps/engine/lib/engine/agents/diario.ex)
  • agent.response (apps/api/src/application/use-cases/llm/send-chat-message.use-case.ts)
  • agent.status (apps/engine/lib/engine/agents/diario.ex)
  • agent.turn (apps/engine/lib/engine/harness/tool_loop.ex)
  • agent.turn_resumed (apps/engine/lib/engine/agents/diario.ex)
  • anamnese.agent_deviation (apps/engine/lib/engine/anamnese/tools/report_agent_deviation.ex)
  • anamnese.analysis (apps/engine/lib/engine/workers/anamnese_worker.ex)
  • anamnese.profile_updated (apps/api/src/application/use-cases/anamnese/record-proficiency.use-case.ts)
  • anamnese.run_completed (apps/api/src/application/use-cases/anamnese/record-proficiency.use-case.ts)
  • anamnese.run_failed (apps/engine/lib/engine/session_events/event.ex)
  • anamnese.run_skipped (apps/engine/lib/engine/session_events/event.ex)
  • architecture.readiness_confirmed (apps/api/src/application/use-cases/agents/offer-infra-handoff.use-case.ts)
  • artifact.business_rule (apps/engine/lib/engine/agents/arquiteto_server.ex)
  • artifact.decision_record (apps/api/src/application/use-cases/backlog/perguntas-em-aberto.use-case.ts)
  • artifact.insight (apps/engine/lib/engine/harness/tools/emit_insight.ex)
  • artifact.module_map (apps/api/src/application/use-cases/architecture/create-module-map.use-case.ts)
  • artifact.open_question — ⚠️ не описан выше (apps/engine/lib/engine/harness/decisoes_do_projeto.ex)
  • artifact.plano_de_teste (apps/engine/lib/engine/gates/qa_lead_server.ex)
  • artifact.product_brief (apps/engine/lib/engine/agents/arquiteto_server.ex)
  • artifact.project_image (apps/engine/lib/engine/harness/ambiente_do_agente.ex)
  • artifact.prototipo_navegavel (apps/engine/lib/engine/agents/ux_designer_tools.ex)
  • artifact.qa_verdict (apps/engine/lib/engine/gates/qa_lead_server.ex)
  • artifact.rfc_staff (apps/engine/lib/engine/agents/staff_tools.ex)
  • artifact.secops_verdict — ⚠️ не описан выше (apps/engine/lib/engine/gates/secops_agent_server.ex)
  • artifact.threat_model (apps/engine/lib/engine/agents/dev_lead_tools.ex)
  • backlog.epic_created (apps/api/src/application/use-cases/backlog/create-epic.use-case.ts)
  • backlog.epic_without_story (apps/engine/lib/engine/agents/po_server.ex)
  • backlog.handoff_not_offered (apps/engine/lib/engine/agents/po_server.ex)
  • backlog.semantic_duplicate_check_skipped (apps/api/src/application/use-cases/backlog/verificar-duplicata-semantica.use-case.ts)
  • backlog.semantic_duplicate_warned (apps/api/src/application/use-cases/backlog/verificar-duplicata-semantica.use-case.ts)
  • backlog.story_archived (apps/api/src/application/use-cases/backlog/corrigir-historia.use-case.ts)
  • backlog.story_completed (apps/api/src/application/use-cases/backlog/complete-story.use-case.ts)
  • backlog.story_created (apps/api/src/application/use-cases/backlog/create-story.use-case.ts)
  • backlog.story_demoted (apps/api/src/application/use-cases/architecture/create-module-map.use-case.ts)
  • backlog.story_modules_assigned (apps/api/src/application/use-cases/architecture/assign-story-modules.use-case.ts)
  • backlog.story_overlap_warned (apps/api/src/application/use-cases/backlog/create-story.use-case.ts)
  • backlog.story_promotion_proposed (apps/api/src/application/use-cases/backlog/complete-story.use-case.ts)
  • backlog.story_promotion_returned (apps/api/src/application/use-cases/backlog/return-story.use-case.ts)
  • backlog.story_transitioned (apps/api/src/application/use-cases/backlog/transition-story.use-case.ts)
  • backlog.story_updated (apps/api/src/application/use-cases/backlog/corrigir-historia.use-case.ts)
  • backlog.task_blocked (apps/api/src/application/use-cases/execution/mark-task-blocked.use-case.ts)
  • backlog.task_claimed (apps/api/src/application/use-cases/execution/claim-next-task.use-case.ts)
  • backlog.task_created (apps/api/src/application/use-cases/backlog/create-task.use-case.ts)
  • backlog.task_merge_conflict (apps/api/src/application/use-cases/actions/execute-git-action.use-case.ts)
  • backlog.task_status_changed (apps/api/src/application/use-cases/actions/execute-git-action.use-case.ts)
  • backlog.task_unblocked (apps/api/src/application/use-cases/execution/unblock-task.use-case.ts)
  • bootstrap.adopted_as_is (apps/api/src/application/use-cases/git/decide-bootstrap-plan.use-case.ts)
  • bootstrap.plan_approved (apps/api/src/application/use-cases/git/decide-bootstrap-plan.use-case.ts)
  • bootstrap.repository_adopted (apps/api/src/application/use-cases/git/adopt-repository.use-case.ts)
  • bootstrap.step_acknowledged — ⚠️ не описан выше (apps/api/src/application/use-cases/git/acknowledge-protection-failure.use-case.ts)
  • bootstrap.step_completed (apps/api/src/application/use-cases/git/bootstrap-runner.ts)
  • bootstrap.step_degraded (apps/api/src/application/use-cases/git/bootstrap-runner.ts)
  • bootstrap.step_failed (apps/api/src/application/use-cases/git/bootstrap-runner.ts)
  • bootstrap.step_skipped (apps/api/src/application/use-cases/git/bootstrap-runner.ts)
  • bootstrap.step_started (apps/api/src/application/use-cases/git/bootstrap-runner.ts)
  • budget.threshold_crossed (apps/api/src/application/use-cases/llm/record-llm-usage.use-case.ts)
  • chat.message (apps/api/src/application/use-cases/agents/send-agent-message.use-case.ts)
  • chat.message_cancelled (apps/engine/lib/engine/agents/fila_de_mensagens.ex)
  • chat.message_delivered (apps/engine/lib/engine/agents/fila_de_mensagens.ex)
  • chat.message_queued (apps/engine/lib/engine/agents/fila_de_mensagens.ex)
  • chat.structured_question (apps/engine/lib/engine/agents/reidratacao.ex)
  • chat.structured_question_answered (apps/api/src/application/use-cases/agents/answer-structured-question.use-case.ts)
  • delegation.completed (apps/api/src/application/use-cases/execution/record-delegation.use-case.ts)
  • delegation.dispensed (apps/api/src/application/use-cases/execution/record-delegation.use-case.ts)
  • delegation.failed (apps/api/src/application/use-cases/execution/record-delegation.use-case.ts)
  • event.appended (apps/engine/lib/engine/sessions/live_broadcast.ex)
  • execution.activated (apps/api/src/application/use-cases/execution/activate-execution.use-case.ts)
  • execution.parallelization_accepted (apps/api/src/application/use-cases/execution/accept-parallelization.use-case.ts)
  • execution.parallelization_suggested (apps/api/src/application/use-cases/execution/activate-execution.use-case.ts)
  • gate.interrupted (apps/engine/lib/engine/gates/gate_rescuer.ex)
  • gate.rescue_parked (apps/engine/lib/engine/gates/gate_rescuer.ex)
  • gate.scanner (apps/engine/lib/engine/gates/scanner.ex)
  • handoff.accepted (apps/api/src/application/use-cases/agents/accept-handoff.use-case.ts)
  • handoff.auto_accept_failed (apps/api/src/application/use-cases/agents/aceitar-handoff-automaticamente.use-case.ts)
  • handoff.offered (apps/api/src/application/use-cases/agents/create-handoff.use-case.ts)
  • handoff.superseded (apps/api/src/application/use-cases/agents/ciclo-de-vida-do-handoff.service.ts)
  • infra.artifact_blocked (apps/api/src/application/use-cases/execution/mark-infra-artifact-blocked.use-case.ts)
  • infra.correction_delivered (apps/engine/lib/engine/infra/infra_lead_server.ex)
  • infra.correction_queued (apps/engine/lib/engine/infra/infra_lead_server.ex)
  • infra.gate_changed (apps/api/src/application/use-cases/execution/record-infra-gate-verdict.use-case.ts)
  • instruction.rolled_back (apps/api/src/application/use-cases/instructions/rollback-instruction.use-case.ts)
  • llm.turn (apps/engine/lib/engine/sessions/engine_api_client.ex)
  • necessity.validated (apps/api/src/application/use-cases/agents/confirm-readiness.use-case.ts)
  • permission.granted (apps/api/src/application/use-cases/actions/approve-always-action.use-case.ts)
  • pr.gate_changed (apps/api/src/application/use-cases/execution/open-gate.use-case.ts)
  • project.git_connected (apps/api/src/application/use-cases/git/handle-git-oauth-callback.use-case.ts)
  • project.repository_adopted (apps/api/src/application/use-cases/git/adopt-repository.use-case.ts)
  • project.repository_provisioned (apps/api/src/application/use-cases/git/provision-repository.use-case.ts)
  • project.workspace_verified (apps/api/src/application/use-cases/iam/confirm-project-workspace.use-case.ts)
  • proposed_action.approved (apps/api/src/application/use-cases/actions/approve-action.use-case.ts)
  • proposed_action.created (apps/api/src/application/use-cases/actions/propose-action.use-case.ts)
  • proposed_action.denied (apps/api/src/application/use-cases/actions/deny-action.use-case.ts)
  • proposed_action.executed (apps/api/src/application/use-cases/actions/execute-git-action.use-case.ts)
  • psychologist.analysis_completed (apps/api/src/application/use-cases/execution/propose-hypotheses.use-case.ts)
  • psychologist.analysis_failed (apps/engine/lib/engine/workers/psychologist_worker.ex)
  • psychologist.analysis_skipped (apps/engine/lib/engine/workers/psychologist_worker.ex)
  • psychologist.hypothesis_accepted (apps/api/src/application/use-cases/execution/accept-hypothesis.use-case.ts)
  • psychologist.hypothesis_accepted_for_anamnese (apps/api/src/application/use-cases/execution/accept-hypothesis.use-case.ts)
  • psychologist.hypothesis_dismissed (apps/api/src/application/use-cases/execution/dismiss-hypothesis.use-case.ts)
  • psychologist.hypothesis_proposed (apps/api/src/application/use-cases/execution/propose-hypotheses.use-case.ts)
  • rag.feedback (apps/api/src/application/use-cases/rag/record-rag-feedback.use-case.ts)
  • rag.search (apps/api/src/application/use-cases/rag/hybrid-search.use-case.ts)
  • readiness.confirmed (apps/api/src/application/use-cases/agents/confirm-readiness.use-case.ts)
  • session.activated (apps/api/src/db/seed.ts)
  • session.closed (apps/engine/lib/engine/outbox/drain.ex)
  • session.closed_abnormally (apps/engine/lib/engine/outbox/drain.ex)
  • session.created (apps/api/src/application/use-cases/sessions/create-session.use-case.ts)
  • session.draining (apps/engine/lib/engine/shutdown.ex)
  • tool.call (apps/engine/lib/engine/agents/arquiteto_server.ex)
  • tool.result (apps/engine/lib/engine/agents/arquiteto_server.ex)

TODO(humano): type — свободная string в application/ports/session-event-repository.port.ts — ничто не мешает опечатке молча создать новый тип, и ничто не гарантирует, что эта страница покрывает все. Union в TypeScript, экспортируемый из packages/shared, решил бы обе проблемы и позволил бы этому списку быть сгенерированным, а не поддерживаемым вручную. Пока его нет, список выше — датированное извлечение из точек эмиссии.