Skip to content

Сессия — это ДВЕ вещи

Решение #223. Слово «сессия» в TAUSIK склеивает два понятия с разной судьбой, и именно склейка мешала ответить, что из этого можно выбросить.

Что этоСвойство чего
Непрерывность работыhandoff: что сделано, что в работе, что дальше, о чём предупредитьСвойство РАБОТЫ
Гигиена контекста агенталимит 180 активных минут (SENAR 9.2), ёмкость 200 вызовов, счётчик чекпоинта (SENAR 9.3)Свойство КОНТЕКСТНОГО ОКНА агента

Половины теперь не сцеплены. Раньше были — тремя способами, и каждый выглядел безобидно:

  • session_handoff отказывал, если окно закрыто. Наоборот: агент, упёршийся в лимит 180 минут, — ровно тот, кому нужнее всего записать, на чём он остановился. Отказ терял документ, ради которого лимит и существует.
  • Сохранение handoff обнуляло tool_call_count. Сброс счётчика — гигиена, и теперь это отдельная названная операция reset_checkpoint_counter, а не побочный эффект записи документа. /checkpoint по-прежнему делает и то и другое — но явно и в этом порядке.
  • Гейт ёмкости молча пропускал всё, если открытой сессии не было. См. ниже.

Почему непрерывность НЕ отменена

Задача, из которой выросло это разделение, предлагала выбросить первую половину: её роль якобы взяла git-проекция. Предпосылка опровергнута замером, а не мнением — четыре факта:

  1. Проекция выключена по умолчанию. state.auto_export не имеет дефолта нигде: DEFAULT_CONFIG при бутстрапе ключа state не содержит, а резолвер при любой ошибке отдаёт False. Свежий проект проекции не имеет.
  2. Сессии не проецируются вообще. ENTITY_DIRS = (epics, stories, tasks, decisions, memory). Даже при включённой проекции handoff в дерево не попадает.
  3. У полей handoff нет другого дома. Дерево несёт «что изменилось» — статус задачи, её журнал, решения, память. next_steps, warnings и in_progress[].state («шаг 3 из 5») не имеют колонки нигде, кроме sessions.handoff.
  4. Проекция сама называет себя неполной. Её докстринг перечисляет непокрытое поимённо, покрытие держат ~18 ручных вызовов, все триггеры fail-open.

Условие будущего отказа названо явно: handoff должен получить проецируемый дом, то есть sessions должно войти в ENTITY_DIRS. Условие проверяется тестом tests/test_session_two_halves.py::TestTheDropConditionIsNotMet — если он покраснеет, это не регрессия, а сигнал пересмотреть #223.

Что при этом опровергнуто в пользу задачи: калибровка не зависит от сессий совсем. calibration_drift и per_tier_metrics читают только таблицу tasks (call_budget/call_actual/tier/completed_at), без единого join к sessions.

Отсутствие сессии — это НЕ «безлимитно»

Гейт ёмкости раньше возвращался рано, если открытой сессии нет: проверка на 200 вызовов переставала проверять и не говорила об этом ни слова. Хуже того, это переворачивало стимул — самым дешёвым способом обойти отказ по ёмкости было закончить сессию и не начинать новую.

Теперь отсутствие сессии — явный отказ для задачи, объявившей бюджет. Задача без бюджета стартует как раньше: гейт имеет мнение только о том, что попросило себя учитывать.

Что ещё молча выключается без открытой сессии

Это важно знать, потому что все перечисленные механизмы отказывают записывая ноль, а не ошибку — узнать о потере можно было только по пустым отчётам:

МеханизмЧто происходит
Usage-телеметрия (posttool_usage)строки не пишутся вовсе ⇒ tasks.cost_actual_usd и tokens_actual остаются нулями у каждой задачи, бюджет по стоимости не срабатывает
Token-метрики.tausik/token_metrics.jsonl не пополняется; tausik metrics tokens печатает «данных пока нет»
Пиннинг моделиstarted_model_id / done_model_id остаются NULL, model_mismatch больше не срабатывает никогда
Срез brain «за эту сессию»считается по всему времени и выдаёт себя за сессионный — не пусто, а неверно; самый опасный случай из списка
Каденция аудита (SENAR 9.5)«3 сессии с последнего аудита» не наступает никогда

Поэтому отказ гейта ёмкости называет tausik session start — это одно действие восстанавливает всё перечисленное.

Что осталось без изменений

Таблица sessions, session_start/session_end, handoff, метрики, режущие по сессиям (throughput «задач на сессию», session_hours, окно token-метрик «последние N сессий», каденция аудита). Разделение убрало сцепку, а не данные.

Смотрите также