# Ретроспектива TASK-source-reuse-project-documents

[HTML-отчёт с графиками](TASK-source-reuse-project-documents.html)

## Контекст

- Задача: `TASK-source-reuse-project-documents`.
- Pull Request (PR, запрос на слияние): [#2814](https://github.com/prikotov/TasK/pull/2814).
- Период анализа: от запуска задачи до merge (слияния) PR.
- Цель ретроспективы: определить, на каких этапах расходовались токены AI-агентов, и предложить изменения процесса, снижающие расход без ухудшения качества.

## Методика

Статистика рассчитана по локальным Codex session logs (журналам сессий) основного агента и сабагентов.

- Этапы определены по сообщениям пользователя, времени запуска сабагентов и переходам между видами работ.
- Ожидаемая погрешность распределения между соседними этапами: около 5%.
- Значения отражают объём model tokens (токенов модели), а не денежную стоимость.
- Cached input (закэшированный вход) обычно дешевле обычного input, поэтому экономия raw tokens (сырых токенов) не равна экономии стоимости.
- Agent active time (активное время агента) рассчитано как объединённое wall-clock time (фактическое прошедшее время) от начала до завершения agent turns (ходов агента), включая выполнение tools, tests и ожидание сабагентов. Параллельная работа сабагентов повторно не суммируется.
- Human response wait (ожидание ответа человека) рассчитано как простой после завершения работы агента до следующего явного сообщения пользователя. Метрика включает сон, личные дела, чтение PR и анализ кода: достоверно разделить эти причины по журналам нельзя.
- Human response wait распределено по тому временному этапу, в котором фактически находился интервал ожидания, а не по предшествующему запросу.
- Автоматические goal continuations (продолжения цели), environment context и служебные сообщения не считаются запросами человека.
- Один вызов модели определяется как отдельное увеличение cumulative token counter (накопительного счётчика токенов) основного агента или сабагента после исключения унаследованного fork context.
- Функциональная классификация токенов выполнена по ближайшему tool call (вызову инструмента). Один model call (вызов модели) может одновременно содержать анализ, правку и запуск проверки, поэтому для этой классификации ожидаемая погрешность выше — около 10–15%.
- Категория tool feedback (обратная связь инструментов) включает запуск и разбор результатов `make check`, targeted tests (целевых тестов), статического анализа, E2E и миграций. Последующая правка кода учитывается как development, если она произошла в отдельном model call.

## Итоговое потребление

| Категория | Токены |
|---|---:|
| Input (входной контекст) | 329,4 млн |
| Из них cached input | 319,5 млн |
| Non-cached input (новый вход) | 9,9 млн |
| Output (ответы и действия агента) | 667 тыс. |
| Reasoning output (токены рассуждения, отражённые в метриках) | 210 тыс. |
| **Общий объём** | **330,1 млн** |

Главный количественный вывод: 96,8% входного контекста было закэшировано. Значительная часть токенов ушла не на создание нового кода, а на многократную передачу длинной истории основному агенту и сабагентам.

## Стоимость моделей

Эквивалентная стоимость задачи по pay-per-token pricing (тарификации за токены) составила **$180,47**. Использованы цены из локального отчёта `/home/dp/MyProjects/.ai_sync/analytics/tokens/index.html`, собранного 8 августа 2026 года:

| Модель | Fresh input, $/1M | Cached input, $/1M | Output, $/1M |
|---|---:|---:|---:|
| `gpt-5.6-sol` | $5,00 | $0,50 | $30,00 |
| `gpt-5.6-terra` | $2,00 | $0,20 | $12,00 |

Расчёт выполнен по формуле `fresh input × input rate + cached input × cache rate + output × output rate`. Reasoning tokens входят в output и повторно не тарифицируются.

| Модель | Fresh input | Cached input | Output | Стоимость | Доля стоимости |
|---|---:|---:|---:|---:|---:|
| `gpt-5.6-sol` | 6,52 млн | 206,37 млн | 404 тыс. | $147,90 | 82,0% |
| `gpt-5.6-terra` | 3,39 млн | 113,16 млн | 263 тыс. | $32,57 | 18,0% |
| **Итого** | **9,91 млн** | **319,53 млн** | **667 тыс.** | **$180,47** | **100%** |

В структуре расходов cached input стоил $125,82 (69,7%), fresh input — $39,38 (21,8%), output — $15,28 (8,5%). Несмотря на десятикратную скидку к fresh input, длинный cached context остался главным источником стоимости.

Это расчёт «как если бы оплата выполнялась за каждый токен». Фактическое списание по Codex subscription (подписке Codex) может отличаться и из журналов задачи не определяется.

## Общие метрики выполнения

| Метрика | Значение |
|---|---:|
| Полное elapsed time (календарное время) | 7 212 минут, или около 120 часов |
| Agent active time | 773 минуты, или около 12 часов 53 минут |
| Human response wait | 6 439 минут, или около 107 часов 19 минут |
| Вызовы модели | 2 828 |
| Явные запросы пользователя | 153 |
| Среднее число вызовов модели на запрос пользователя | 18,5 |
| Средний raw context на вызов модели | около 117 тыс. токенов |

Agent active time составило около 10,7% календарного времени, Human response wait — около 89,3%. Само ожидание человека токены не расходует, но возобновление длинной сессии после паузы снова передаёт модели накопленный контекст.

## Разработка и служебные расходы

Ниже приведена взаимоисключающая классификация всех token-bearing model calls (вызовов модели с ненулевым расходом токенов). При смешанном вызове категория выбиралась по доминирующему действию: проверка → delivery (публикация) → правка → анализ.

| Категория работы | Вызовы модели | Доля вызовов | Токены | Доля токенов | Стоимость | Доля стоимости |
|---|---:|---:|---:|---:|---:|---:|
| Правки production code, tests и documentation | 403 | 14,3% | 47,3 млн | 14,3% | $26,85 | 14,9% |
| Анализ кода, architecture review и code review | 925 | 32,7% | 98,1 млн | 29,7% | $64,25 | 35,6% |
| Обсуждение, объяснение решений и reasoning без tool call | 936 | 33,1% | 117,8 млн | 35,7% | $51,99 | 28,8% |
| Tool feedback: проверки и разбор их результатов | 472 | 16,7% | 57,2 млн | 17,3% | $32,58 | 18,1% |
| Delivery: подготовка commit, push, создание и обновление PR | 65 | 2,3% | 7,1 млн | 2,2% | $2,74 | 1,5% |
| Оркестрация плана и сабагентов | 26 | 0,9% | 2,6 млн | 0,8% | $2,07 | 1,1% |
| **Итого token-bearing calls** | **2 827** | **100%** | **330,1 млн** | **100%** | **$180,47** | **100%** |

Ещё один служебный вызов модели не имел положительного token delta (изменения счётчика токенов), поэтому общее число вызовов в сессии — 2 828, а в таблице — 2 827.

В узком смысле измеримый non-development operational overhead (операционный расход вне анализа и правок) — tool feedback, delivery и orchestration: **66,9 млн токенов, или 20,3%**, **$37,39, или 20,7% стоимости**, и 563 вызова модели. В буквальном смысле вне непосредственного редактирования файлов находилось 85,7% токенов, но считать весь анализ, review и обсуждение «не разработкой» некорректно: без них нельзя было определить и проверить решение.

### Feedback loops инструментов

За сессию `make check` запускался **27 раз**. До публикации первоначального решения в PR было 7 запусков, после неё — ещё **20 запусков**. В число запусков входят перезапущенные и прерванные фоновые команды, поэтому это количество стартов процесса, а не 27 полностью завершившихся независимых прогонов.

| Период | Запуски `make check` | Все токены периода | Из них прямой tool feedback | Доля прямого tool feedback в периоде |
|---|---:|---:|---:|---:|
| От старта до первоначального PR с успешным `make check` | 7 | 24,5 млн | 6,7 млн | 27,4% |
| После первоначального PR до принятого финального состояния | 20 | 305,6 млн | 50,5 млн | 16,5% |
| **Вся сессия** | **27** | **330,1 млн** | **57,2 млн** | **17,3%** |

Таким образом, доведение первоначального решения до первого опубликованного состояния с успешным `make check` потребовало 24,5 млн токенов, из которых 6,7 млн непосредственно относились к проверкам и обработке их feedback (обратной связи). После первого PR ещё 305,6 млн токенов были потрачены на изменение требований и архитектуры, пользовательское review, повторные правки и финальную проверку; только 50,5 млн из них можно прямо отнести к инструментальным feedback loops.

Последующие исправления ошибок инструментов в отдельных model calls попали в категорию правок. Поэтому 57,2 млн — измеримая нижняя граница стоимости tool feedback. Теоретическая верхняя граница вместе со всеми следующими за проверками правками — 104,5 млн токенов, или 31,6%, но она завышена: значительная часть правок была вызвана замечаниями пользователя и сменой архитектурных решений, а не падениями проверок.

Важно: последнее финальное выполнение полного `make check` не стало полностью green (успешным) из-за двух зафиксированных несвязанных Integration errors (ошибок интеграционных тестов): `ModelPriceModel::getProvider` и `InvitationModel::getCount`. Targeted checks (целевые проверки), static analysis (статический анализ), unit tests и Source pipeline прошли, и пользователь принял это состояние. Поэтому 305,6 млн нельзя интерпретировать как стоимость «починки одного упавшего `make check`»: это стоимость всего rework после первоначального решения до согласованной точки приёмки.

### Commit и PR delivery

Подготовка commits, выполнение `push`, создание и последующие обновления PR потребовали **65 вызовов модели и 7,1 млн токенов**, то есть **2,2%** общего расхода. Итоговый PR содержал 42 commits. В delivery не включены чтение diff, архитектурный анализ и code review: они учтены отдельно, даже если выполнялись непосредственно перед commit.

### Размер итогового PR

| Категория | Добавлено | Удалено | Изменено строк |
|---|---:|---:|---:|
| Production code и конфигурация | 1 471 | 266 | 1 737 |
| Tests (тесты) | 2 392 | 369 | 2 761 |
| Documentation и todo | 276 | 34 | 310 |
| Прочее | 16 | 0 | 16 |
| **Итого** | **4 155** | **669** | **4 824** |

Дополнительно PR затронул 191 файл и содержал 42 commits (коммита).

На одну итоговую изменённую строку пришлось около 68,4 тыс. raw tokens или около 2,1 тыс. non-cached input tokens. Это диагностическая, а не производительная метрика: итоговый diff не содержит код, который создавался и затем удалялся во время rework (повторной работы).

## Распределение по этапам

| Этап | Токены | Доля | Agent active, мин | Human response wait, мин | Вызовы модели |
|---|---:|---:|---:|---:|---:|
| Первичная разработка | 15,4 млн | 4,7% | 285,1 | 0 | 240 |
| Первичный self-review (самопроверка) и code review (ревью кода) | 9,3 млн | 2,8% | 21,6 | 294,6 | 129 |
| Проверка PR пользователем и исправление замечаний | 276,6 млн | 83,8% | 411,1 | 6 133,4 | 2 234 |
| Cross-user E2E (сквозной межпользовательский сценарий), финальная регрессия и подготовка merge | 28,7 млн | 8,7% | 55,5 | 11,2 | 225 |
| **Итого** | **330,1 млн** | **100%** | **773,3** | **6 439,2** | **2 828** |

### Детализация пользовательского review

| Подэтап | Токены | Доля общего объёма | Agent active, мин | Human response wait, мин | Вызовы модели |
|---|---:|---:|---:|---:|---:|
| API, conventions (конвенции), DTO, mapper и relation model | 102,5 млн | 31,0% | 183,7 | 1 233,2 | 842 |
| `CreateByUri`, workflow (процесс обработки), transaction boundary (граница транзакции) и locks (блокировки) | 124,8 млн | 37,8% | 155,3 | 4 165,6 | 954 |
| Atomic events (атомарные события), chunks readiness, logging и финальный pipeline | 49,4 млн | 15,0% | 72,0 | 734,6 | 438 |
| **Итого пользовательского review** | **276,6 млн** | **83,8%** | **411,1** | **6 133,4** | **2 234** |

Около 69% всех токенов ушло на исправление двух групп проблем:

1. Неверно определённые границы API, публичного статуса и domain relation (доменной связи).
2. Несколько итераций перепроектирования `CreateByUri` и Source workflow.

## Что было хорошо

### Содержательное пользовательское review

Замечания пользователя выявили архитектурно значимые проблемы:

- readiness (готовность) должна быть project-scoped (ограниченной проектом);
- `Document List` не должен агрегировать посторонний статус;
- состояние подготовки должно принадлежать relation `Source ↔ Project`;
- handler (обработчик) должен иметь ясную границу атомарности;
- `lockForUpdate` нельзя добавлять без доказанной необходимости;
- события и logging должны соответствовать conventions;
- project-specific processing settings нельзя смешивать с global Source;
- примитивный handler готовности документов не оправдывал межмодульный разрыв.

Итоговое решение стало существенно лучше первоначального.

### Финальный reviewer обнаружил регрессию тестового покрытия

Независимый reviewer заметил, что новый cross-user E2E заменил существующий same-user reuse test (тест повторного использования одним пользователем). Старый сценарий был восстановлен до merge.

### Сильное итоговое тестовое покрытие

В результате проверяются:

- повторное добавление Source одним пользователем;
- использование одного `SourceModel` проектами разных пользователей;
- project-scoped documents и chunks;
- реальный путь `Send → RAG → RetrievalChunks`;
- отсутствие cross-project leakage (утечки между проектами);
- неизменность global Source workflow;
- время повторной подготовки;
- полный Source pipeline.

Финальный Source pipeline: `17 tests`, `235 assertions` — успешно.

### Технический долг не был скрыт

Спорные project-scoped processing settings вынесены в отдельную backlog task (задачу бэклога), а не закреплены как окончательное решение.

## Что стоит улучшить

### Усилить первоначальный architecture review

До первого PR не были обнаружены:

- нарушение ответственности `Document List`;
- неверное понимание global и project-scoped status;
- лишний mapper в Controller;
- неудачная отдельная preparation entity/table;
- проблемы transaction/event boundary;
- спорные блокировки;
- нарушения conventions в Criteria, Value Object и imports;
- неправильное место запуска project preparation.

Формальное review прошло, но значительную часть фактического review затем выполнил пользователь.

### Заменить локальные исправления системным аудитом

После первого замечания по `ListController` следовало проверить весь diff по тем же признакам:

- Controller responsibility;
- публичный API status;
- Application orchestration;
- Domain relation;
- persistence model;
- event transaction boundary.

Вместо этого работа часто шла последовательными циклами «одно замечание — одна локальная правка — следующее замечание».

### Исключить спекулятивные изменения

В PR появлялись, а затем удалялись или существенно менялись:

- status mapping в `Document List`;
- отдельная preparation table/entity;
- `ResolveProjectSourcePreparationStatusServiceInterface`;
- `lockForUpdate`;
- запуск preparation из ветки `step === null`;
- дополнительный `DocumentIdVo`;
- прямой вызов handler;
- отдельный `MarkDocumentChunksReadyCommandHandler`;
- несколько вариантов transaction handling;
- разные варианты обновления Source metadata.

Каждая такая итерация требовала повторного анализа кода и контекста.

### Ограничить контекст сабагентов

Поздние сабагенты получали почти всю многодневную историю, хотя для работы им обычно требовались:

- актуальный commit range (диапазон коммитов);
- постановка задачи;
- применимые conventions;
- несколько ключевых файлов;
- список архитектурных invariants (инвариантов).

Полная история была главным техническим источником расхода cached input.

### Запускать review после стабилизации архитектуры

Часть reviewer проверяла diff, который затем радикально менялся. Review нестабильного решения имеет низкую ценность и создаёт повторную работу.

### Улучшить автоматическое информирование

Пользователю приходилось запрашивать статус вручную. Кроме ухудшения взаимодействия, каждый дополнительный turn (ход диалога) повторно прикладывал длинный контекст.

## Что добавить в процесс

### Architecture Gate перед реализацией

Для изменений pipeline, DDD и API до кода фиксировать небольшой decision record (запись решений):

1. Какой объект владеет состоянием?
2. Какова transaction boundary?
3. Какие события публикуются и когда?
4. Кто запускает Messenger job (задачу очереди)?
5. Что является global, а что project-scoped?
6. Какие межмодульные зависимости допустимы?
7. Какие conventions применяются?
8. Какие существующие сценарии нельзя сломать?

Для этой задачи до реализации следовало зафиксировать:

- `SourceModel::$status` — внутренний lifecycle;
- readiness принадлежит `ProjectSourceModel`;
- публичное чтение Source всегда содержит project context;
- `Document List` остаётся только списком;
- повторное добавление не запускает global workflow;
- handler атомарен;
- queue delivery не компенсируется DB lock без отдельного основания;
- события публикуются в согласованной transaction model.

### Разделить архитектурное и кодовое review

Architecture review проверяет:

- ownership;
- layers и module boundaries;
- transaction/event model;
- API contract;
- persistence model.

Code review проверяет:

- типизацию;
- naming и formatting;
- тесты;
- performance;
- edge cases.

### Передавать сабагенту компактный handoff

Предпочтительный формат:

```text
Task:
Commit range:
Files:
Architecture invariants:
Relevant conventions:
Required tests:
Out of scope:
```

Использовать ограниченный fork context (контекст ответвления): `fork_turns: "none"` или только последние 2–5 turns, если полная история не требуется.

### Запускать pattern audit после первого системного замечания

Если обнаружено нарушение одного типа, одним проходом проверять все аналогичные участки:

- Controllers;
- Mappers;
- Application services;
- межмодульные вызовы;
- Criteria и Value Object;
- transaction и lock участки.

### Ограничить количество rework cycles

После третьей существенной переделки одной области прекращать локальные исправления и выполнять root-cause review (анализ первопричины):

```text
Третья переделка CreateByUri
→ остановить изменения
→ зафиксировать invariants
→ сравнить с исходным workflow
→ перепроектировать блок целиком.
```

### Фиксировать baseline checks до разработки

В начале задачи сохранять состояние:

- `make check`;
- Integration tests;
- известных ошибок;
- актуального Source pipeline.

Это позволяет однозначно отделить новые ошибки от существующих.

### Ввести token budget по этапам

| Этап | Целевой диапазон |
|---|---:|
| Анализ и Architecture Gate | 5–10% |
| Реализация | 35–45% |
| Self-review и code review | 15–20% |
| Исправления review | не более 25% |
| Tests и merge | 10–15% |

Если исправления становятся дороже первоначальной реализации, следует остановить локальные правки и пересмотреть архитектуру.

## Что убрать или сократить

### Убрать

- Полный history fork для каждого сабагента.
- Спекулятивные «best practice» изменения без проверки существующего кода и conventions.
- Review нестабильного diff.
- Новые Application services и Value Object без самостоятельной семантики.
- Ручное polling длительных команд через пользовательские сообщения.

### Сократить

- Циклы «один комментарий — одна отдельная итерация разработки».
- Повторные объяснения уже отвергнутых решений.
- Передачу полного stdout тестов вместо краткого summary и пути к логу.
- Частые промежуточные отчёты без нового результата или блокера.

### Оставить

- Commit и push перед отчётом пользователю.
- Self-review и независимый code review.
- Полный E2E перед merge.
- Явную фиксацию технического долга.

Эти действия следует выполнять по milestone (контрольной точке), а не после каждой микроправки.

## Рекомендации и прогноз экономии

### Изолировать контекст сабагентов

**Действие:** использовать компактный handoff и ограниченный `fork_turns`, начинать новый thread после крупных milestones.

**Обоснование:** 96,8% input составлял cached context; основная масса токенов связана с повторным чтением истории.

**Прогноз:** сокращение raw tokens на 55–70%.

### Ввести Architecture Gate

**Действие:** до реализации согласовать ownership, API, transaction/event boundaries и state machine.

**Обоснование:** около 69% токенов ушло на переделку API, модели, workflow и транзакций.

**Прогноз:** сокращение rework на 35–50%, либо ещё 10–20% общего расхода после оптимизации контекста.

### Выполнять batch review

**Действие:** после первого системного замечания проверять весь diff по обнаруженному pattern.

**Обоснование:** многие замечания относились к одному классу ошибок и могли быть обнаружены за один проход.

**Прогноз:** уменьшение количества review turns на 30–50%, экономия ещё 5–10% общего расхода.

### Проверять только стабильное решение

**Действие:** архитектура → реализация → targeted tests → self-review → independent review.

**Обоснование:** часть review выполнялась по коду, который затем удалялся.

**Прогноз:** экономия 5–8%.

### Автоматизировать monitoring и сокращать логи

**Действие:** самостоятельно ждать завершения команд, уведомлять только о результате или блокере, сохранять большие логи вне диалога.

**Обоснование:** это уменьшает служебные turns и повторную передачу контекста.

**Прогноз:** экономия 2–5%.

Эффекты рекомендаций пересекаются, поэтому их нельзя складывать напрямую.

| Сценарий | Ожидаемый расход | Эквивалентная стоимость | Экономия |
|---|---:|---:|---:|
| Фактический результат этой задачи | 330 млн | $180,47 | — |
| Консервативно улучшенный процесс | 120–150 млн | около $66–82 | 55–64% |
| Реалистичная цель | 80–120 млн | около $44–66 | 64–76% |
| Оптимистичный сценарий при стабильной архитектуре | 60–80 млн | около $33–44 | 76–82% |

Стоимость будущих сценариев оценена при неизменном соотношении моделей и типов токенов; это ориентир, а не точный billing forecast (прогноз списаний). По non-cached input реалистичная цель — снижение с 9,9 млн до 5–7 млн, то есть примерно на 30–50%.

## Итог

Основные потери возникли не из-за объёма итогового кода и не из-за необходимости review, а из сочетания:

1. недостаточного первоначального архитектурного анализа;
2. последовательного исправления отдельных симптомов;
3. передачи полной многодневной истории новым сабагентам;
4. review до стабилизации решения.

Самые результативные изменения процесса — короткий Architecture Gate и изолированный контекст каждого сабагента. Они должны обеспечить большую часть прогнозируемой экономии.
