Files
docs/audits/codex-sessions-token-audit-2026-08-26.md
T

757 lines
20 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.
# Codex Sessions Token Audit
Дата анализа: 2026-08-26
## Контекст
Анализ выполнен по rollout-сессиям Codex за день для pet-проекта, где используется:
- SDD (Spec-Driven Development);
- OpenSpec;
- `AGENTS.md`;
- skills;
- subagents;
- многошаговый workflow от discovery/design до implementation/review.
Цель аудита — понять, почему Codex расходует лимиты слишком быстро, определить основные источники token usage и сформировать практические направления оптимизации процесса разработки.
---
# Executive Summary
Разобраны все 9 rollout-файлов. Fork/subagent-сессии были учтены отдельно, чтобы не посчитать унаследованную историю дважды.
Главный вывод:
> **Проблема действительно есть, и она почти не связана с генерацией кода как таковой. Основной расход создаёт большое количество последовательных model ↔ tool циклов на уже разросшемся контексте.**
## Общая статистика
| Работа | Model calls | Input | Cached input | Uncached input | Output |
|---|---:|---:|---:|---:|---:|
| Аудит SDD/OpenSpec + subagents | **254** | **26.51M** | 25.70M | 812K | 112K |
| Выбор UI skill | 2 | 53K | 4K | 49K | 1K |
| Редизайн карточки акции + Curie | **120** | **13.37M** | 12.90M | 469K | 41K |
| Редизайн операций + Faraday | **182** | **20.95M** | 20.42M | 534K | 80K |
| **Итого** | **558** | **60.88M** | **59.02M** | **1.86M** | **234K** |
Ключевые цифры:
- **96.9% всего input — cached input**;
- всего около **3.1% input был новым**;
- output модели — около **0.38% относительно input**;
- reasoning — около **66K токенов**, то есть не является основным источником расхода;
- средний model call получал примерно **109 000 input-токенов**;
- из них в среднем:
- около **105 770 cached**;
- около **3 341 новых**.
Иными словами, очередной `rg`, `sed`, `git diff` или другой tool call приводит к новому model call с огромным уже накопленным контекстом.
---
# 1. Главная проблема — слишком много model round-trips
В SDD-сессии:
```text
254 model calls
26.51M input tokens
≈104K input / call
```
Карточка акции:
```text
120 model calls
13.37M input
≈111K / call
```
Операции:
```text
182 model calls
20.95M input
≈115K / call
```
Получается почти линейная зависимость:
```text
большой context
×
много model calls
=
огромный cumulative input
```
Типичный дорогой паттерн:
```text
model
↓
sed ...
↓
model ← опять ~130K input
↓
rg ...
↓
model ← опять ~140K
↓
git diff
↓
model ← опять ~150K
↓
sed ...
↓
model ← опять ~160K
```
Более экономный вариант:
```text
model
↓
├─ rg ...
├─ git diff --stat
├─ sed relevant-range...
└─ ...
↓
model
```
То есть **batch/parallel tool calls — один из самых сильных рычагов оптимизации**.
Хороший контрольный пример есть прямо в логах: сессия «какой skill выбрать» выполнила **8 tool calls всего за 2 model calls**. Это значительно более экономный паттерн.
---
# 2. Контекст реально разрастается до 200K+
Максимальный input одного model call:
| Сессия | Median | Max | Context window |
|---|---:|---:|---:|
| SDD/OpenSpec | ~128K | **216.5K** | 258.4K |
| Карточка акции | ~133K | **213.5K** | 258.4K |
| Операции | ~119K | **231.0K** | 258.4K |
Одна из сессий дошла примерно до:
```text
231K / 258K ≈ 89% context window
```
Codex уже был вынужден делать context compaction.
Особенно показательно распределение cumulative input:
- в основной SDD-сессии **83.6%** input пришлось на вызовы, где контекст уже был больше 100K;
- в карточке акции — **83.5%**;
- в операциях — **77.3%**.
Если чисто математически ограничить model calls уровнем около 100K input, потенциально можно было бы убрать порядка:
```text
~16.4M input tokens
```
Это не означает, что нужно вводить жёсткий hard-cap 100K, но цифра показывает масштаб проблемы.
---
# 3. Длинная сессия «одна feature от начала до конца» слишком дорогая
Текущий flow приблизительно выглядит так:
```text
research
↓
design
↓
OpenSpec proposal
↓
delta specs
↓
design
↓
tasks
↓
implementation
↓
tests
↓
fix
↓
review
↓
docs
↓
archive
```
Если всё это живёт в одной conversation, implementation в конце тащит за собой:
```text
весь research
+ старые tool outputs
+ обсуждение дизайна
+ предыдущие ответы
+ OpenSpec
+ прочитанный source code
+ git diff
+ test output
+ skills
+ instructions
+ ...
```
Хотя для конкретной операции, например:
```text
исправить BrokerageOperationRow
```
большая часть этого контекста уже не нужна.
## Рекомендуемый workflow
Не отказываться от SDD. Наоборот, использовать OpenSpec как естественную границу контекста:
```text
Session 1 — Discovery / Design
↓
proposal + specs + design
Session 2 — Planning
↓
approved artifacts
↓
tasks.md
Session 3 — Implementation
↓
читает только approved OpenSpec
+ affected source files
Session 4 — Verification / Review
↓
git diff
+ approved specs/design/tasks
Session 5 — Archive
```
Каждая следующая сессия получает **результат предыдущей в структурированной форме**, а не всю историю того, как к нему пришли.
Это хорошо сочетается с SDD: артефакт становится интерфейсом между агентными сессиями.
---
# 4. Слишком много полного чтения файлов
В командах за день часто встречались:
```text
SKILL.md 35 раз
tasks.md 35
AGENTS.md 32
spec.md 30
git diff 24
design.md 23
proposal.md 21
schema.yaml 20
engineering-governance.md 15
audit-remediation.md 16
domain-glossary.md 11
system-overview.md 10
```
Это не означает, что каждый файл каждый раз читался полностью, но хорошо показывает характер поведения агента.
Особенно заметна root-инструкция:
> перед работой прочитать engineering-governance, system-overview и domain-glossary
В результате каждый новый агент снова читает эти документы.
Например, одни и те же governance-файлы читали:
```text
root
Kierkegaard
Nash
Curie
Faraday
...
```
Это цена текущего governance-подхода.
Сам `AGENTS.md` при этом небольшой — примерно 2230 символов. Его размер не является проблемой.
## Что лучше изменить
Вместо обязательного чтения нескольких больших документов перед любой работой:
```text
AGENTS.md
Before work:
1. Determine affected repositories.
2. Read their AGENTS.md.
3. Consult docs/development/engineering-governance.md
only for the relevant gate/policy.
4. Read system-overview only for cross-service/
architectural changes.
5. Read domain-glossary only when domain semantics
are involved.
```
То есть сделать документацию **lazy context**, а не mandatory context.
---
# 5. Некоторые tool outputs слишком большие
В SDD-сессии встречались результаты команд размером:
```text
40 137 chars
36 937 chars
34 621 chars
32 936 chars
32 874 chars
...
```
В одном случае:
```text
Warning: truncated output
original token count: 15,592
Total output lines: 1006
```
То есть агент запросил больше тысячи строк.
Другой пример:
```bash
bash -x scripts/verify-openspec-planning.test.sh
```
дал:
```text
566 lines
original token count: 14,118
```
`bash -x` для обычной успешной verification — дорогой паттерн.
## Более эффективный подход
Вместо:
```bash
sed -n '1,320p' file1
sed -n '1,380p' file2
sed -n '1,300p' file3
```
лучше:
```text
rg / symbol search
↓
identify relevant section
↓
sed -n '120,180p'
```
То есть `rg` должен быть основным инструментом discovery, а `sed` — точечным чтением найденного диапазона.
---
# 6. `git diff` — ещё один заметный источник расхода
`git diff` встречается минимум **24 раза**.
Некоторые outputs достигают:
```text
16K tokens
14K tokens
11K tokens
...
```
Иногда diff перечитывается почти целиком несколько раз.
## Рекомендуемый стандарт
```text
git status --short
↓
git diff --stat
↓
git diff --name-only
↓
только затем:
git diff -- path/to/relevant/file
```
Полный relevant diff имеет смысл один раз читать независимому reviewer.
Нежелательно выполнять:
```bash
git diff
```
на multi-repo workspace после большой реализации без предварительного narrowing.
---
# 7. Subagents стоят токенов, но не являются главной проблемой
После удаления унаследованных cumulative counters:
## SDD audit
Основной agent:
```text
20.45M input
```
Kierkegaard:
```text
+1.07M
```
Peirce:
```text
+4.26M
```
Nash:
```text
+0.73M
```
Итого:
```text
26.51M
```
Subagents добавили примерно:
```text
~6.06M input
≈23% workload
```
Это существенно, но запрещать subagents не стоит.
У них есть важное преимущество: собственный context обычно меньше:
```text
Kierkegaard max ~102K
Peirce max ~112K
Nash max ~79K
Curie max ~62K
Faraday max ~79K
```
Иногда выгоднее:
```text
200K root
↓
spawn focused reviewer with 30–70K
```
чем заставлять root делать ещё несколько десятков model calls с 200K-контекстом.
## Важное ограничение
Subagent должен получать **узкую задачу**.
Нежелательно без необходимости использовать:
```text
fork_turns="all"
```
В первом SDD workflow именно этот режим использовался и требует оптимизации.
---
# 8. Skills влияют, но не являются проблемой №1
Простой запрос:
```text
какой skill мне использовать?
```
имел первый input примерно:
```text
20 479 tokens
```
То есть в Codex Desktop уже существует около **20K+ стартового context overhead** до серьёзной работы.
В него входят:
- Codex app instructions;
- tool schemas;
- environment;
- plugin information;
- workspace state;
- AGENTS;
- другие системные данные.
Например, только Codex app-context занимает около 35K символов, а список `recommended_plugins` — ещё примерно 6.7K символов.
Это почти невозможно оптимизировать на уровне проекта.
Но skills добавляют дополнительный overhead.
`ui-ux-pro-max` инжектировал примерно:
```text
~16 036 символов skill content
```
Первый model call после этого был около:
```text
26 796 tokens
```
## Рекомендуемая структура больших skills
```text
SKILL.md
↓
короткий orchestration/router
↓
references/
├── colors.md
├── typography.md
├── tables.md
├── finance.md
└── ...
```
Reference-файлы читаются только при необходимости.
Этот подход особенно полезен для собственных больших skills.
---
# 9. Reasoning effort пока не стоит оптимизировать первым
За весь набор:
```text
Input 60,883,487
Output 233,968
Reasoning 66,327
```
Reasoning составляет очень небольшую часть общего расхода.
Даже сильное уменьшение reasoning не решит проблему с десятками миллионов input tokens.
Для механических операций вроде:
```text
npm test
lint
git status
mechanical implementation
```
high reasoning действительно может быть избыточным.
Но по приоритету эта оптимизация значительно ниже context management.
---
# 10. Реальный рост Codex quota
В rollout записывается primary rate limit:
```text
window_minutes: 10080
```
10080 минут = 7 дней.
За исследованный кусок дня показатель изменился примерно так:
```text
начало первой сессии: 33%
после неё: 47%
после карточки: 53%
конец последней: 62%
```
То есть:
```text
33% → 62%
```
или около:
```text
+29 процентных пунктов 7-дневного лимита
```
Ощущение, что Codex слишком быстро расходует quota, подтверждается логами.
---
# Приоритеты оптимизации
| Priority | Изменение | Потенциальный эффект |
|---|---|---|
| 🔴 P0 | **Разделять длинную feature на SDD / implementation / review sessions** | Очень высокий |
| 🔴 P0 | **Сокращать количество model ↔ tool round-trips** | Очень высокий |
| 🔴 P0 | **Batch/parallel независимые tool calls** | Очень высокий |
| 🟠 P1 | Не читать governance/docs полностью перед каждой работой | Высокий |
| 🟠 P1 | `rg → targeted sed`, а не большие `sed/cat` | Высокий |
| 🟠 P1 | `git diff --stat/name-only → targeted diff` | Высокий |
| 🟠 P1 | Ограничивать test/build output | Средне-высокий |
| 🟡 P2 | Не использовать `fork_turns=all` без необходимости | Средний |
| 🟡 P2 | Большие skills разбить на lazy references | Средний |
| 🟢 P3 | Снижать reasoning для механической работы | Низкий относительно остального |
---
# Предлагаемые token budgets
Для дальнейшей разработки можно использовать ориентиры:
```text
Healthy session
initial context: 20–40K
normal working context: <100K
warning: >120K
restart/handoff: >150K
model calls / phase: желательно <50
tool output / call: желательно <3–5K tokens
```
Эти значения следует воспринимать как практические budgets для текущего workflow, а не как жёсткие ограничения Codex.
---
# Основной принцип оптимизации
Не стоит использовать compaction только как последнее средство.
В SDD естественной точкой compaction/handoff должен стать **готовый артефакт**.
Например:
```text
долго обсуждали
↓
получили approved design.md
↓
старый разговор больше не нужен
↓
NEW SESSION
↓
Implement change X according to approved
proposal/specs/design/tasks
```
То есть:
> **SDD artifact должен быть interface между агентными сессиями, а не только документацией внутри одной огромной сессии.**
Это позволяет сохранить качество и одновременно удалить значительную часть исторического шума.
Implementation-agent получает не всю историю обсуждений, а только авторитетные артефакты и необходимый код.
---
# Предлагаемое направление: Token-Efficient SDD v2
Следующий этап оптимизации имеет смысл строить вокруг следующих вопросов:
1. Где именно должны находиться границы Codex sessions.
2. Какие OpenSpec-артефакты должны передаваться между фазами.
3. Какие документы обязательны для чтения, а какие должны загружаться лениво.
4. Когда использовать root agent, а когда focused subagent.
5. Какой context передавать subagent.
6. Какие ограничения ввести для:
- `sed`;
- `cat`;
- `git diff`;
- test output;
- build output;
- debug tracing.
7. Как batch-ить независимые tool calls.
8. Когда автоматически рекомендовать завершить session и начать новую.
9. Какие token budgets использовать как guardrails.
10. Как измерять эффективность изменений по rollout-файлам.
---
# Итог
Текущая проблема не выглядит как:
```text
Codex слишком много думает
```
или:
```text
OpenSpec сам по себе слишком дорогой
```
Основная проблема выглядит так:
```text
большой накопленный context
×
очень много model calls
×
повторное чтение больших outputs/files
=
огромный cumulative input usage
```
Поэтому максимальный эффект даст не сокращение качества спецификаций и не отказ от SDD, а изменение **agent execution model**:
```text
короче sessions
+ artifact handoff
+ lazy context
+ targeted reads
+ narrow diffs
+ compact tool output
+ batched tool calls
+ focused subagents
```
Это должно стать основой следующей версии SDD workflow.