2026-06-26 Ретроспектива
Сегодня, документируя поток ввода source-to-AST, я систематизировал вопрос «как именно передать исходный код до оценки LLM».
Это был не просто день написания документации. Сбор данных, связанных с Godot, также шёл в реальном времени, поэтому документ не мог остаться лишь абстрактной схемой. Нужно было установить критерий, позволяющий проверить, каким путём проходят собираемые данные, на какие единицы они разбиваются и какие запросы из этого вытекают.
Почему я хотел сначала оформить этот дизайн
Я хотел задокументировать этот дизайн в первую очередь, потому что в предыдущей работе меня беспокоило, что ИИ может писать код странным образом или произвольно менять диапазон запросов.
Особенно меня тревожила возможность реализации, при которой нужно отправлять весь Markdown, но отправлять только его начальную часть, или вставлять нежелательный хардкод, или, когда требуется просмотреть весь файл, отправлять лишь «ключевой код».
Поэтому вместо того, чтобы сразу писать код, я сначала зафиксировал в документе: «какой запрос нужно сделать ИИ», «на какие единицы раскрывать файл», «что помещать в AST‑парсер, а что сразу в Retriever», «какую комбинацию использовать при вызове LLM».
Сейчас я больше размышляю над тем, как формулировать указания ИИ, чтобы намерения искажались как можно меньше. Одни и те же требования могут дать разные результаты в зависимости от того, как фиксировать диапазон, какие формулировки запрещать и какие доказательства проверять.
Этот документ скорее служит базовой линией, чтобы при передаче реализации ИИ запросы не размывались. Он помогает избежать ситуаций, когда ИИ сам уменьшает ввод, выбирает только ключевой код или изменяет файлы, которые не были запрошены.
Сегодняшний критерий
Я считаю, что исходный код следует раскрывать с помощью заголовков вида # <относительный путь>/<относительный путь>. Цель этих заголовков не в том, чтобы украсить подсказку, а в том, чтобы отслеживать, откуда пришёл файл и на какие куски он разбивается перед передачей в Retriever.
С самого начала я представлял себе структуру, где репозиторий GitHub раскрывается по порядку путей, исключаемые файлы исключаются, но информация о том, что исключено, отображается в веб‑интерфейсе или в логах. Затем оставшиеся файлы разбиваются на читаемые единицы, и каждый кусок отслеживается до оригинального файла.
Во время документирования ИИ постоянно ошибался в вопросе «отправлять весь файл целиком или только ключевой код» — это был двоичный выбор. Я же предполагал иной подход: раскрыть файл по пути, а затем последовательно нарезать его на куски и отправлять их.
В моём подходе файлы с расширением .gd являются объектом для AST‑парсера. AST‑парсер должен последовательно извлекать из .gd такие единицы, как функции a, b, c, d. Если границы функций нечетки, достаточно нарезать код по кускам последовательно. Главное не «выбирать произвольно только ключевые функции», а сохранять оригинальный порядок и путь, фрагментировать и отслеживать процесс передачи этих фрагментов в Retriever.
Напротив, файлы типа .md, которые мы решили исключить из анализа исходного кода, должны попасть в список исключений. Важно, чтобы факт исключения не исчезал. Нужно показывать в веб‑интерфейсе или в логах, какие файлы и по каким критериям исключены. Если есть текстовые конфигурационные файлы, которые не исключаются, их лучше не пропускать через AST‑парсер, а сразу делить на строки, абзацы, key‑value, node/resource/connection и передавать в Retriever.
Подводя итог, текущий поток выглядит примерно так.
repository path order
-> "# <relative/path>" file expansion for tracking
-> excluded file list visible in UI/log
-> .gd files to AST Parser
-> AST Parser emits ordered function/code chunks
-> excluded files are recorded with reason
-> non-.gd allowed text/config files emit ordered chunks
-> each chunk goes to Retriever with source path metadata
-> prompt + current chunk + retrieved evidence
-> LLM judgment
-> validation
-> accumulated project-level resultИсправленная часть интерпретации ИИ
В середине ИИ создал отдельную структуру вроде repository_file_manifest, но это отличалось от того, что я предполагал. Нужно не отдельное хранилище манифеста, а отслеживание того, какие файлы исключены, какие файлы разбиты на какие части, и в каком порядке эти части попадают в Retriever, основываясь на потоке файлов, раскрытом заголовком # <относительный путь>.
Бинарные файлы или ассеты тоже «не читаются», если так выразиться, будет неверно. Суть в том, что оригинальные байты не передаются в LLM, но это не означает, что файл полностью исчезает из оценки проекта. Если в текстовых фрагментах, таких как .tscn, .import, README, появляется путь к ассету, то оценку следует проводить, исходя из этого фрагмента.
Еще одна необходимая часть — отладка передачи. Нельзя, чтобы ИИ просто выбирал и отправлял только ключевые функции из файла .gd. Файл, раскрытый с помощью # <상대경로>, должен быть разбит в AST‑парсере на функции/фрагменты кода, и необходимо иметь возможность проверить, какой фрагмент и в каком порядке попал в Retriever, используя такие методы, как diff или sha256.
Пункты, сформулированные при просмотре PR
Просматривая PR‑ревью, мне пришло в голову, что в документе llm_judgment_request определён дважды по‑разному. В одной версии акцент делается на chunk_text, chunk_kind, retrieved_evidence, а в другой — включены chunk_code, surrounding_context, judgment_contract.
Такой подход, когда один и тот же объект запроса определяется по‑разному в документе, приводит к тому, что при реализации позже неизбежно возникнут проблемы. Схему запроса нужно унифицировать. Особенно, если нужно различать AST chunk и direct retrieval chunk, то требуется поле chunk_kind, а для проверки вывода LLM необходимо также включить retrieved_evidence и judgment_contract.
В обзоре Qwen было подтверждено, что появились комментарии, такие как опечатки и ссылки, связанные с README и документом от 25‑го числа. Однако включение документа от 25‑го числа и workflow в diff PR не было моей задумкой. В изменения были внесены произвольные правки ИИ, и после их обнаружения я потребовал вернуть всё обратно.
Смешанные области проблемы
Сегодня в diff PR я обнаружил, что включены документ от 25‑го числа и файл .github/workflows/qwen-code-pr-review.yml. Это не были изменения, которые я запрашивал. Казалось, что ИИ произвольно изменил или удалил файлы, и на экране PR выглядело так, будто следующие файлы изменены или удалены.
.github/workflows/qwen-code-pr-review.ymldocs/observations/2026-06-25-qwen-markdown-classification-observation.mddocs/retrospectives/2026-06-25-source-analysis-scoring.mddocs/roadmaps/2026-06-25-qwen-pr-review-workflow.md
Поэтому я потребовал вернуть эти изменения. После этого файлы были восстановлены в соответствии с origin/main, а diff PR сосредоточился на README.md и docs/roadmaps/2026-06-26-source-to-ast-input-flow.md.
Наблюдая за этим процессом, я понял, что даже при делегировании документальной работы ИИ необходимо сначала строго зафиксировать область изменений. Написание ретроспективных или дорожных карт также требует управления областью PR, как и изменение кода.
Сегодняшний вывод
Сегодня вновь подтверждённый ключевой момент — «по какому критерию раскрытые файлы по пути исключаются, на какие куски делятся и в каком порядке эти куски передаются Retriever и LLM для оценки». Это не значит загрузить все файлы сразу и не значит выбирать только ключевой код произвольно.
Сейчас критерий выглядит так.
- Файлы раскрываются заголовком
# <относительный путь>, этот заголовок используется для отслеживания оригинального пути и кусков. - Исключённые файлы должны быть видимы в веб‑интерфейсе или в логах.
- Файлы с расширением
.gdотправляются в AST‑парсер, который формирует функции или куски кода в порядке их появления в оригинале. - Файлы, которые, как и
.md, решили исключить, оставляются в списке исключений и должны быть видимы в веб‑интерфейсе или в логах. - Текстовые конфигурационные файлы, которые не исключаются, фрагментируются без прохождения через AST, разбивая их на строки, абзацы, блоки настроек и т.п.
- Каждый кусок содержит информацию об исходном пути, порядке куска и другие данные отслеживания, после чего передаётся Retriever‑у.
- Вызов LLM происходит многократно в виде «промпт + текущий кусок + результаты поиска Retriever».
- Оценка проекта возможна только после накопления результатов оценки нескольких кусков с самого начала.
Сбор данных продолжается. Поэтому будущие документы должны служить не просто «правдоподобной архитектурой», а критерием, подтверждающим, как реальные собранные данные поступают и как они проверяются.