- Удалена пустая секция 14.4.2 (Circular validation) - Исправлена нумерация: 23.11 → 23.10 - Убрана проза после «Источников» в главе 14 - Ненумерованные H3 в главах 13, 14, 19 — убрана числовая нумерация - Глава 10: Termination Conditions повышен до ## (был ошибочно вложен в ## 10.5) - Глава 24: опечатка «простой» → «прост», строчная «глава» → «Глава»
76 KiB
ГЛАВА 16. АРХИТЕКТУРА КОДА, ДРУЖЕСТВЕННАЯ ИИ
В 2026 году ваш код читают не только коллеги — его читают AI-агенты. Claude Code, Cursor Agent, Windsurf, Devin — это не «помощники», это полноценные потребители вашей кодовой базы. Они индексируют файлы, парсят функции, строят граф зависимостей. И качество их работы напрямую зависит от того, как ваш код организован.
Примечание: Эта глава — об архитектуре кода, и примеры «до/после» — её основной обучающий инструмент. Фрагменты ниже — иллюстративный псевдокод, показывающий паттерны и анти-паттерны. Для генерации production-кода используйте AI-промпты, приведённые в каждой секции.
Прежде чем разбирать принципы — посмотрите на реальную ситуацию.
Код, который сломал AI-агента
Команда попросила Cursor Agent добавить скидку для оптовых заказов. Вот что агент увидел:
# app.py — 1200 строк, фрагмент
class App:
def handle(self, req):
d = self.db.get(req.args["id"])
if d and d[7] > 0: # d[7]? Что это??
p = d[3] * d[5] # d[3]? d[5]??
if self._check(d): # Что проверяет?
p = p * 0.9 # Магическое число
self._do(d, p) # Что делает?
return {"ok": True}
Агент не понял, где цена, где количество, что за d[7], и сгенерировал код со скидкой, применённой не к тому полю. Баг ушёл в прод.
Та же логика, переписанная в стиле, дружественном для ИИ, — файл order/pricing.py на 45 строк: типизированная функция calculate_order_price(items: list[OrderItem], discount_percent: float) -> OrderTotal с docstring, описывающим аргументы, возврат и семантику. Cursor Agent получил задачу «добавить оптовую скидку 15% при заказе от 100 единиц». Он прочитал контракт, увидел discount_percent, добавил одно условие — и всё заработало с первого раза.
Промпт для генерации кода: «Напиши Python-модуль
order/pricing.py(< 50 строк). Функцияcalculate_order_price(items: list[OrderItem], discount_percent: float = 0.0) -> OrderTotal. Docstring в Google style с Args, Returns. Используй Decimal для денежных расчётов. Dataclasses для OrderItem (quantity, unit_price) и OrderTotal (subtotal, discount_amount, final_total).»
Вывод: архитектура кода — это уже не только про людей. Это протокол общения с AI-инструментами, которые пишут, рефакторят и ревьюят ваш код каждый день.
16.1. Маленькие модули лучше монолита
Почему модель ошибается в монолитном коде
Представьте кубики LEGO. Каждый кубик — простой: 2×4, красный, с пупырышками. Но из сотни таких кубиков можно собрать что угодно — от домика до космического корабля. А теперь представьте, что вместо кубиков вам дали гипсовый монолит в форме замка. Хотите добавить башню? Нужно ломать стену, надеяться, что крыша не обвалится, и подпирать конструкцию изолентой.
Так же AI-агенты работают с вашим кодом. Маленькие модули — это LEGO-кубики: каждый делает что-то одно, его легко понять, заменить или скомбинировать. Монолит — это гипсовый замок: тронешь одно — сломается другое.
LLM обрабатывает код как последовательность токенов с ограниченным окном контекста. В 2026 году это особенно важно: Copilot, Cursor и Windsurf автоматически индексируют вашу кодовую базу, и маленькие файлы помещаются в их контекстное окно целиком. Монолитный файл в 2000 строк создаёт несколько проблем:
1. Размывание внимания: в файле на 2000 строк (~6000–10000 токенов) внимание распределяется на множество функций, классов и import'ов. Когда модель модифицирует функцию на строке 1500, она «видит» функцию на строке 50, но уделяет ей минимум внимания (Lost in the Middle).
2. Неявные зависимости: в монолите зависимости скрыты. Функция process_order() на строке 800 может зависеть от глобальной переменной на строке 12, вспомогательной функции на строке 300 и класса на строке 600. Модель должна отследить все эти связи — Transformer умеет это делать, но каждая дополнительная связь увеличивает вероятность ошибки.
3. Переполнение контекста: если файл не помещается в окно контекста — модель работает с фрагментом. Изменение одного фрагмента без видимости другого -> несогласованности.
Оптимальный размер модуля
| Размер файла | Токены (Python) | Качество генерации | Рекомендация |
|---|---|---|---|
| <100 строк | ~300–500 | Отлично | Идеал |
| 100–300 строк | 500–1500 | Хорошо | Приемлемо |
| 300–500 строк | 1500–2500 | Средне | Рефакторить |
| 500+ строк | 2500+ | Ненадёжно | Разбить обязательно |
Правило: один модуль ≤ 100 строк, одна функция ≤ 30 строк, одна ответственность.
Как это выглядит на практике
До (монолит): order_service.py — 800 строк. Класс OrderService с семью методами: create_order (100 строк), validate_order (60), calculate_price (80), apply_discount (40), process_payment (120), send_notification (50), update_inventory (70) + helpers, constants, error handlers.
После (модули):
order/
├── __init__.py
├── models.py # 40 строк: Order, OrderItem, OrderStatus
├── validation.py # 60 строк: validate_order()
├── pricing.py # 80 строк: calculate_price(), apply_discount()
├── payment.py # 70 строк: process_payment()
├── notifications.py # 50 строк: send_notification()
├── inventory.py # 50 строк: update_inventory()
└── service.py # 60 строк: create_order() — оркестрация
Каждый файл — это отдельный LEGO-кубик. Он помещается в один промпт с запасом. AI-агент (будь то Claude Code, Cursor или Devin) может модифицировать pricing.py, не загружая весь сервис. А при ревью кода автоматические инструменты парсят каждую функцию отдельно — чем чище контракт, тем точнее ревью.
16.2. Контракт функции как фиксатор смысла
Зачем нужен контракт
Контракт функции — это этикетка на продукте. Когда вы берёте с полки йогурт, вам не нужно его открывать, чтобы понять: состав, калорийность, срок годности — всё на этикетке. Точно так же работает контракт функции: типы аргументов (состав), docstring (описание), тип возврата (результат) — всё видно без чтения тела функции.
Это семантический якорь для модели (Глава 1). Типы, докстроки, pre/post-conditions — всё это фиксирует, что функция делает, не заставляя модель угадывать. В 2026-м это особенно критично: AI-инструменты ревью кода (встроенные в GitHub, GitLab, Cursor) парсят каждую функцию отдельно — чистый контракт = точное автоматическое ревью.
Минимальный контракт
Минимальный контракт включает: имя функции (семантика), типы аргументов и возврата (формат данных), docstring (спецификация поведения), раздел Raises (граничные условия), пример использования (конкретный I/O для калибровки). Без контракта модель вынуждена угадывать формат, поведение и границы.
Промпт для генерации кода: «Напиши Python-функцию
calculate_order_total(items: list[OrderItem], discount_percent: float, tax_rate: float) -> OrderTotal. Контракт: items — непустой список, discount_percent и tax_rate — дроби [0.0, 1.0]. Скидка применяется до налога. Добавь Google-style docstring с Args, Returns, Raises (ValueError на невалидные аргументы) и Example с конкретным расчётом. Используй Decimal для точных денежных расчётов.»
Что даёт контракт модели
| Элемент | Что фиксирует для модели | Без контракта |
|---|---|---|
| Имя функции | Семантика (calculate = вычислить) | Угадывает из контекста |
| Типы аргументов | Формат входных данных | Может принять str вместо float |
| Типы возврата | Формат выходных данных | Может вернуть dict вместо dataclass |
| Docstring | Полная спецификация поведения | Угадывает по имени |
| Raises | Граничные условия | Может проигнорировать ошибки |
| Example | Конкретный I/O для калибровки | Нет якоря для формата |
Комментарии: полезен intent, а не пересказ кода
Есть соблазн думать, что для AI чем больше комментариев, тем лучше. Это не совсем так. Современные исследования по code translation показывают, что особенно полезны комментарии о намерении: зачем нужен модуль, какова общая цель функции, какой контракт или инвариант должен сохраняться. А вот комментарии уровня «увеличиваем i на 1» нередко добавляют шум и даже ухудшают трансформации кода.
Лучший комментарий для AI — это не покадровый пересказ очевидного, а сжатая спецификация смысла: что делает функция в системе, почему решение устроено именно так, какие ограничения нельзя нарушать и где безопасно менять код. Поэтому комментарии стоит ставить на границах абстракций — у модулей, публичных функций, сложных инвариантов и точек принятия решений. Если строка кода и без комментария очевидна человеку, почти наверняка не нужно объяснять её и модели.
GRACE: semantic header как карта файла
Для AI-агента лучший файл — это файл, у которого смысл виден сверху вниз. Перед телом модуля полезно поставить короткий машиночитаемый заголовок: что делает модуль, с чем связан, какой инвариант защищает и какие опасные пути уже отвергнуты.
# [DEF:OrderPricing:Module]
# @PURPOSE: Рассчитать итоговую цену заказа.
# @LAYER: Domain
# @RELATION: DEPENDS_ON -> [DiscountPolicy:Module]
# @INVARIANT: Скидка применяется до налога.
# @RATIONALE: Денежная логика централизована в одном модуле.
# @REJECTED: Не вычислять цену повторно в API-слое.
# [/DEF:OrderPricing:Module]
Такой header — не замена коду, а карта перед входом в здание. Он помогает модели быстро решить, стоит ли вообще читать файл целиком, а человеку — понять, можно ли безопасно менять модуль.
Почему это имеет смысл. Работы по code generation показывают, что полезен не любой комментарий, а именно слой требований и намерений. В TOSEM-статье ShortenDoc DocString рассматривается как носитель пользовательских требований; авторы показывают, что обычные методы prompt compression для code generation начинают заметно деградировать уже около 10% сокращения, тогда как специализированный docstring-подход даёт 25–40% compression без потери качества в условиях их эксперимента. Это признак того, что короткая intent-спецификация содержит концентрированную полезную информацию. При этом MSR-исследование про contextual data в code completion показывает более нюансированную картину: помогают прежде всего осмысленные multi-line comments, а не любое дополнительное текстовое украшение.
Отсюда практическое правило: header должен кодировать purpose / invariants / relations / rejected paths, а не пересказывать построчно реализацию. Сложностные уровни, лимит 300 строк и прочие governance-правила можно смело использовать как дисциплину команды — но честно: это уже не «физика трансформера», а ваша рабочая политика.
Semantic markup без валидатора быстро деградирует
Разметка становится инженерной системой только тогда, когда у неё есть автоматическая проверка. Если semantic header существует лишь как красивый комментарий, через несколько спринтов он начинает врать: закрывающие теги расходятся, @RELATION указывают на удалённые узлы, а старые @REJECTED молча исчезают.
Практический минимум — дешёвый deterministic checker, который проверяет:
- у каждого
[DEF]есть парный[/DEF]; - обязательные поля header'а не потерялись;
@RELATIONуказывают на существующие public/shared узлы;- file-local contracts не утекли в shared graph случайно;
- нарушение правил даёт non-zero exit code в CI.
Для таких semantic envelopes полный AST не всегда лучший первый инструмент. AST отлично понимает структуру кода, но плохо подходит для comment-level contracts и machine-readable headers. Поэтому на практике хорошо работает гибрид: регулярные выражения и построчный валидатор для semantic boundaries плюс AST только там, где действительно важно проверить imports, callable names или topology.
$ python tools/check_semantics.py
ERROR app/services/pricing.py: missing closing [/DEF:OrderPricing:Module]
ERROR appgraph.xml: unknown relation target [DiscountPolicy:Module]
WARN tests/test_pricing.py: helper block has no anchor
Это полезное инженерное правило для любой кодовой базы, дружественной ИИ: semantic markup должен жить рядом с тестами и линтерами, а не только в агентных инструкциях. Иначе у вас появляется красивый язык контрактов без механизма, который удерживает его от распада.
Pre/Post-conditions и Design by Contract
Ещё мощнее — контракт с явными pre/post-conditions и инвариантами. Для функции transfer_funds(from_account, to_account, amount) pre-conditions фиксируют: amount > 0, достаточный баланс, разные счета, оба активны. Post-conditions гарантируют: баланс отправителя уменьшился, получателя увеличился, транзакция залогирована. Инвариант: суммарный баланс не изменился. Pre/post-conditions записываются и в docstring, и как executable assertions в теле функции.
Модель видит pre/post-conditions и генерирует код, который по конструкции их соблюдает. Без них — каждое ограничение нужно угадывать.
Промпт для генерации кода: «Напиши Python-функцию
transfer_funds(from_account: Account, to_account: Account, amount: Decimal) -> TransferResultс Design by Contract. Добавь в docstring: Pre-conditions (amount > 0, достаточный баланс, разные ID, активные счета), Post-conditions (балансы изменены, транзакция залогирована), Invariant (суммарный баланс неизменен). Реализуй pre- и post-conditions как executable assertions.»
16.3. Zero-Context Survival: код должен быть понятен без промпта
Тест на автономность
Вспомните карточку экстренной инструкции в самолёте или на огнетушителе. Она работает, даже если вы никогда не видели этот аппарат раньше: пиктограммы, нумерация шагов, цветовая маркировка — нулевой контекст, полная ясность. Ваш код должен быть такой же карточкой: когда AI-агент открывает файл впервые, он должен понять всё без дополнительных объяснений.
Код, сгенерированный ИИ, должен быть полностью самодокументированным — работать и быть понятным без оригинального промпта. Это критерий качества:
Вопросы для проверки:
- Может ли новый разработчик понять функцию, прочитав только код?
- Все ли зависимости явны (imports, типы, конфигурация)?
- Понятны ли границы ответственности (что функция делает и чего НЕ делает)?
- Есть ли обработка ошибок для реальных сценариев?
Антипаттерн: контекстно-зависимый код
Функция process(data) без типов, с обращением к item[2], неизвестным threshold и загадочной transform — требует промпт для понимания. В противоположность — самодокументированная filter_high_temperature_readings с typed dataclass SensorReading, явным порогом threshold_celsius и однострочной реализацией. Второй вариант не требует контекста: новый разработчик или AI-агент поймёт всё из сигнатуры.
Промпт для генерации кода: «Рефакторинг: есть функция
process(data), которая фильтрует элементы по неявному порогуthresholdи применяет неявнуюtransform. Перепиши в Zero-Context Survival стиле: создай frozen dataclassSensorReading(sensor_id, timestamp, temperature_celsius), напиши функциюfilter_high_temperature_readings(readings: Sequence[SensorReading], threshold_celsius: float = 40.0) -> list[SensorReading]. Все зависимости явные, типы на всех аргументах.»
16.4. "Small Simple Blocks": линейный код лучше переусложнённого DRY
Проблема чрезмерной абстракции
DRY (Don't Repeat Yourself) — полезный принцип, но его чрезмерное применение создаёт проблемы для AI-генерации.
Переабстрагированный код — это иерархия PricingStrategy(ABC) → StandardPricing → DiscountPricing + DiscountFactory → BulkDiscount / NoDiscount. Шесть классов, три уровня косвенности — чтобы посчитать subtotal × (1 - discount). Модель должна отследить всю цепочку, чтобы понять, что делает одна операция.
Линейный код — одна функция calculate_order_price(items, discount_percent) -> Decimal: посчитать subtotal, применить скидку, вернуть результат. Три строки логики, нулевая косвенность.
Промпт для генерации кода: «Напиши Python-функцию
calculate_order_price(items: list[OrderItem], discount_percent: float = 0.0) -> Decimal. Линейный стиль, без Strategy pattern. Посчитай subtotal как сумму quantity × unit_price, примени скидку, верни результат. Документируй в Google-style docstring.»
Почему линейный код лучше для AI
- Меньше косвенности: модель не должна отслеживать цепочку
Strategy -> Factory -> Discount -> apply(). - Все шаги видимы: в линейном коде каждый шаг — одна строка. В абстрактном — каждый шаг спрятан за интерфейсом.
- Модификация проще: чтобы изменить расчёт, достаточно изменить одну функцию, а не всю иерархию.
- Тестирование проще: один вход → один выход, без моков и dependency injection.
Когда абстракция оправдана
| Критерий | Линейный код | Абстракция |
|---|---|---|
| Вариантов < 3 | if/elif | Strategy pattern |
| Код используется 1–2 раза | Дублирование | Helper function |
| Логика < 30 строк | Inline | Отдельный класс |
| Требования стабильны | Прямой код | Зависит |
| Требования часто меняются | Зависит | Абстракция с контрактом |
| Вариантов > 5 | Спагетти | Strategy/Registry |
Правило WET (Write Everything Twice): дублируйте код до тех пор, пока не увидите три одинаковых фрагмента. Тогда — и только тогда — абстрагируйте. Преждевременная абстракция опаснее дублирования.
16.5. Как писать код, который AI легко модифицирует
Принципы кода, дружественного ИИ
1. Явные зависимости через аргументы (Dependency Injection простыми словами):
Dependency Injection звучит сложно, но идея простая: вместо того чтобы функция сама доставала себе всё нужное из глобальных переменных, она получает всё через аргументы. Представьте: вместо «я сам пойду в магазин за молоком» — «передайте мне молоко в руки». Для AI-агента это означает: он видит все зависимости прямо в сигнатуре, не рыская по всему проекту. Пример: вместо get_user(), которая обращается к глобальным db и current_user_id — get_user(db: Session, user_id: int) -> User | None.
2. Один файл = одна концепция:
# ✗ models.py — 500 строк с User, Order, Product, Payment, Notification
# ✓
models/
├── user.py # User, UserRole
├── order.py # Order, OrderItem, OrderStatus
├── product.py # Product, Category
├── payment.py # Payment, PaymentMethod
└── notification.py # Notification, NotificationType
3. Конфигурация через переменные, не через код:
Вместо magic numbers (if retry_count > 3 and elapsed > 30) — именованные константы MAX_RETRIES = 3, TIMEOUT_SECONDS = 30 с использованием в условии и информативным сообщением об ошибке. AI-агент сразу понимает семантику и может безопасно изменить значение.
4. Тесты рядом с кодом (почему это критично для AI-агентов):
AI-агенты (Claude Code, Cursor Agent, Devin) работают циклично: написал код → запустил тест → увидел ошибку → исправил. Если тест лежит рядом с кодом, агент находит его мгновенно. Если тесты в отдельной папке tests/ с другой структурой — агент тратит токены на поиск и может обновить не тот файл. Кроме того, агент использует тесты как спецификацию: тест показывает, что функция должна делать, какие краевые случаи важны.
pricing/
├── __init__.py
├── calculator.py
├── test_calculator.py # Рядом с кодом, а не в отдельной папке tests/
└── conftest.py
Модель видит тест рядом с реализацией → может обновить оба одновременно.
16.6. Как AI-агенты читают ваш код
Что видит агент, когда открывает проект
В 2026 году AI-агенты — это не просто автокомплит. Claude Code, Cursor Agent, Windsurf, Devin — это полноценные «разработчики», которые навигируют по проекту, читают файлы, запускают тесты и коммитят код. Понимание того, как они это делают, позволяет писать код, который они обрабатывают эффективно.
Шаг 1: Индексация структуры. Агент начинает с дерева файлов. Он видит имена файлов и папок — это его первая карта. order/pricing.py сообщает больше, чем utils/helpers2.py.
Шаг 2: Чтение ключевых файлов. Агент читает конфигурационные файлы (README, pyproject.toml, package.json), затем — файлы, релевантные задаче. У каждого агента ограниченное контекстное окно, поэтому он выбирает, какие файлы загрузить.
Шаг 3: Семантический поиск. Современные IDE (Cursor, Windsurf, Copilot в VS Code) создают эмбеддинги вашего кода. Когда агент ищет «где вычисляется цена заказа», он находит calculate_order_price() по семантическому сходству — но только если имя функции осмысленное.
Шаг 4: Навигация по зависимостям. Агент переходит от функции к её зависимостям через import'ы и type hints. Явные типы = быстрая навигация. Неявные globals = слепое блуждание.
Шаг 5: Цикл редактирования. Агент вносит изменение, запускает тесты, анализирует ошибки. Чем быстрее этот цикл — тем лучше результат.
Что помогает, а что мешает агенту
| Помогает | Мешает |
|---|---|
| Осмысленные имена файлов и функций | utils.py, helpers.py, misc.py |
| Type hints на всех публичных функциях | def process(data) без типов |
| README с описанием архитектуры | Нет документации проекта |
| Тесты рядом с кодом | Тесты в отдельной иерархии tests/ |
| Маленькие файлы (< 100 строк) | Файлы на 1000+ строк |
| Явные import'ы | Магические __getattr__, метапрограммирование |
.cursorrules / AGENTS.md с инструкциями |
Неявные конвенции «у нас так принято» |
Overview graph, AST graph и raw code: почему нужен гибрид
Спор «семантический обзор vs AST-граф» неверно ставить как выбор одного победителя. Разные слои решают разные задачи.
AST/dataflow-слой полезен, когда агенту нужно пройти многошаговую цепочку зависимостей: controller -> service -> repository, интерфейс -> реализация, producer -> consumer. Здесь структурный retrieval действительно выигрывает. DraCo строит repo-specific context graph через dataflow analysis и в своей экспериментальной конфигурации улучшает repository-level code completion в среднем на 3.43% exact match и 3.27% identifier F1 (Cheng et al., ACL 2024). Работа Reliable Graph-RAG for Codebases показывает похожий вывод для архитектурных и code-tracing запросов: детерминированный AST-derived graph даёт более надёжное покрытие и multi-hop grounding, чем vector-only baseline и LLM-extracted graph.
Но production-практика важна не меньше. Cursor документирует codebase indexing через embeddings for each file, а Kilo Code — через Tree-sitter semantic blocks + embeddings + Qdrant. То есть реальные агенты часто используют AST и парсинг как основу индексирования и chunking, а не как единственный интерфейс, с которым модель потом «разговаривает».
Intent/overview-слой решает другую задачу: быстро понять, что это за модуль, ради чего он существует и какие ограничения уже известны. Здесь особенно полезны @PURPOSE, @INVARIANT, @RATIONALE, @REJECTED и верхнеуровневые relations. SpecRover показывает, что specification inference внутри LLM-агента повышает качество генерации патчей: в статье сообщается о росте более чем на 50% относительно AutoCodeRover на полном SWE-Bench (Ruan et al., ICSE 2025). А работа Your Coding Intent is Secretly in the Context показывает, что намеренное восстановление авторского замысла перед completion даёт более 20% относительного выигрыша на задачах уровня целого репозитория — в условиях их эксперимента.
Для дружественной ИИ кодовой базы лучше работает многослойный паттерн:
- Слой обзора и намерения — что это за модуль и чего нельзя ломать.
- Структурный слой — AST, imports, dataflow, call edges.
- Слой привязки к коду — чтение реального кода перед финальной правкой.
- Слой тестов и проверки — тесты и postconditions после изменения.
Это именно тот класс практик, куда логично помещать GRACE. Он не отменяет AST и не заменяет raw code; он даёт модели короткую карту местности перед тем, как она войдёт в детали.
Public truth vs private truth: двухуровневый интерфейс репозитория
Одна из самых полезных идей, которая хорошо оформлена в grace-marketplace, — жёсткая граница между shared/public truth и file-local/private truth.
Shared/public truth — это артефакты уровня проекта: requirements.xml, development-plan.xml, knowledge-graph.xml, verification-plan.xml. Они отвечают на вопросы:
- какие модули вообще существуют;
- каковы их публичные контракты и зависимости;
- какие verification-entry и critical flows к ним привязаны;
- в каком порядке их безопасно реализовывать или менять.
File-local/private truth — это уже заголовок и внутренняя разметка конкретного файла: MODULE_CONTRACT, MODULE_MAP, локальные контракты функций, semantic blocks, CHANGE_SUMMARY, а в варианте GRACE-подобной markdown-разметки — [DEF], @PURPOSE, @RATIONALE, @REJECTED и т. п.
Почему такое разделение важно:
- Shared-артефакты не распухают. Если knowledge graph начинает перечислять каждый private helper, он превращается из карты страны в снимок всех кухонь сразу.
- Снижается drift. Публичная граница меняется реже, чем внутренняя реализация. Значит, общий слой синхронизировать проще.
- Агенту легче выбрать глубину чтения. Сначала он читает boundary-level truth, и только потом — implementation detail в целевом файле.
Практическое правило: shared docs должны отвечать на вопрос «что за модуль и как он связан с другими?», а file-local markup — на вопрос «что именно здесь можно безопасно менять и чего делать нельзя?».
Репозиторий как интерфейс запросов для агента
Важный сдвиг в поздних версиях grace-marketplace — появление слоя запросов, понимающего схему. CLI и навыки репозитория разделяют два режима чтения:
grace module find/show— доступ к shared/public модульной картине;grace file show --contracts --blocks— доступ к local/private контрактам и semantic blocks конкретного файла.
Это очень сильная идея для агентной разработки. Вместо того чтобы каждый раз гнать модель через голый grep, полезно дать ей два разных API чтения:
- найти релевантный модуль и его публичный контекст;
- после этого открыть только нужный файл и только его важные секции.
Такой слой запросов делает из репозитория не просто папку с кодом, а контекстный интерфейс. Для модели это снижает избыточное чтение, уменьшает вероятность схватиться не за тот файл и помогает не путать факты уровня границы модуля с локальными деталями реализации.
Минимальный рабочий паттерн для кодового агента выглядит так:
grace module find auth
→ grace module show M-AUTH --with verification
→ grace file show src/auth/index.ts --contracts --blocks
→ только потом чтение/редактирование сырого кода
Это не отменяет embedding search и AST traversal. Скорее наоборот: semantic search помогает найти кандидатов, structural graph помогает пройти multi-hop зависимости, а слой запросов даёт короткую проверенную выжимку, с которой агент начинает работу.
Практика 2026: патч не в один выстрел, а через короткий цикл поиска и проверки
Метаобзор 2026 года по механике LLM полезен именно тем, что соединяет проектирование запросов, обучение в контексте и масштабирование вычислений на этапе инференса в одну инженерную картину. Для кодовых задач из этого следует очень прикладной вывод: качество патча определяется не красотой одной формулировки, а качеством цикла — как агенту показали формат задачи, сколько вариантов он пробует и чем эти варианты проверяются.
1. Стабилизируйте каркас промпта. Не переписывайте системный промпт заново под каждую задачу. Держите постоянный шаблон: задача -> целевые файлы -> ограничения -> инварианты -> чем проверяем -> формат ответа. Для репозитория это важнее, чем художественные формулировки. Если вы даёте несколько демонстрационных примеров, пусть они фиксируют именно форму результата: список файлов, дифф, тест-план, чек-лист приёмки.
2. Порождайте несколько патчей только там, где поиск действительно нужен. Для переименования, мелкого CRUD и однотипных правок хватит одного прохода и тестов. Для миграции схемы, неоднозначного багфикса, сложного SQL, оптимизации алгоритма или многофайлового рефакторинга лучше сразу закладывать 3–5 кандидатов патча и выбирать лучший по верификатору. Это дешевле, чем десять раз просить одну и ту же модель «подумать ещё» в том же контексте.
3. Пусть побеждает верификатор, а не риторика модели. Для кода внешний верификатор почти всегда сильнее внутреннего самообъяснения. Базовый стек: pytest, типизация (mypy или pyright), линтер (ruff/eslint), проверка схемы, контрольный дифф, интеграционный smoke-тест. Практическое правило простое: выбирайте самый маленький дифф, который проходит проверки и не ломает инварианты.
4. Давайте модели ровно столько рассуждения, сколько нужно для аудита. Для сложной задачи полезен краткий план в 3–5 пунктов: какие файлы менять, какие риски проверить, чем валидировать итог. Но длинный многостраничный монолог редко даёт дополнительную ценность. Если после короткого плана патч и проверки уже согласованы, дальнейшее «размышление вслух» обычно только расходует токены и повышает шанс уйти в сторону.
Промпт для генерации кода: «Собери пайплайн
generate_patch_candidates(task, repo_context)на Python. Вход: описание задачи, список целевых файлов, инварианты, команды верификации. Шаги: (1) сгенерировать 3 кандидата патча в едином формате, (2) прогнать для каждого тесты, линтер и типизацию, (3) выбрать минимальный дифф, прошедший все проверки, (4) вернутьbest_patch,verification_report,rejected_candidates. Используй asyncio для параллельного прогона проверок.»
Калибруйте шаблон на истории реального репозитория
Лучший промпт для кода не угадывают, а подбирают на собственных задачах. Возьмите 20–30 реальных тикетов из истории проекта и сравните 2–3 версии каркаса: например, «короткий план + diff» против «только диффа», или «один кандидат» против «3 кандидата + верификатор». Смотрите не на красоту объяснения, а на инженерные метрики:
- долю задач, где патч проходит тесты с первой попытки;
- число ручных правок после ответа агента;
- точность выбора файлов;
- среднюю стоимость одного успешно закрытого тикета.
Именно так стоит относиться к контуру запросов в коде: как к конфигурации, которую можно оптимизировать по метрике, а не как к магическому тексту.
Иерархия инструкций защищает агента от заражённого контекста
Ещё один практический вывод из свежих работ по inference и безопасности: кодовый агент нельзя учить одинаково доверять всем кускам контекста. В репозитории всегда есть шум — старые комментарии, устаревшие README, треды в issue-трекере, случайные примеры, чужие SQL-сниппеты. Поэтому полезно зафиксировать явную иерархию:
- Задача пользователя и критерии приёмки.
- Правила репозитория:
AGENTS.md,.cursorrules, контракты модулей, тесты. - Структурные факты: типы, AST, imports, dataflow.
- Нестабильный контекст: issue-описания, старые комментарии, внешние вставки и примеры.
Если README противоречит тесту, доверяйте тесту. Если комментарий спорит с контрактом функции, доверяйте контракту. Если внешний фрагмент кода предлагает «срезать угол», но нарушает инвариант из @INVARIANT, агент должен отклонить такой путь, а не послушно продолжать. Для production-команды это одна из самых дешёвых и полезных защит: она одновременно улучшает качество патчей и снижает риск того, что агент подхватит вредное указание из неавторитетного контекста.
Пример: как имена файлов влияют на агента
# ✗ Агент не понимает, где искать
src/
├── utils.py # 400 строк всего подряд
├── helpers.py # Ещё 300 строк
├── core.py # «Ядро» из 800 строк
└── main.py
# ✓ Агент находит нужное за секунды
src/
├── auth/
│ ├── login.py
│ ├── tokens.py
│ └── permissions.py
├── orders/
│ ├── pricing.py
│ ├── validation.py
│ └── fulfillment.py
└── notifications/
├── email.py
└── sms.py
16.7. Деградация кода при long-horizon генерации: уроки SlopCodeBench
Проблема: код проходит тесты, но становится немодифицируемым
До 2026 года все основные бенчмарки для coding agents оценивали одно: проходит ли код тесты сейчас. SWE-bench, HumanEval, LiveCodeBench — все они измеряют snapshot correctness. Вы чините баг, код проходит тесты — успех. Что происходит с этим кодом через неделю, месяц, десять итераций — никого не волновало.
SlopCodeBench (Orlanski et al., 2026) показал то, о чём инженеры догадывались: агентный код деградирует. Причём предсказуемо и измеримо.
Эксперимент: 20 задач, каждая — цепочка из 3–8 чекпоинтов. Агент получает спецификацию, пишет код. Затем — расширенную спецификацию (новые требования) и обязан модифицировать собственный код с предыдущего шага. Никаких reference solutions, никаких подсказок. Только то, что он сам написал раньше.
Результаты по 11 моделям (включая Opus 4.6, GPT-5.4, Sonnet 4.6):
- Ни одна модель не решила ни одной задачи end-to-end. Лучший strict solve rate: 17.2% (Opus 4.6).
- Verbosity растёт в 89.8% траекторий. Агенты генерируют дублирующийся код, identity-конструкции, никому не нужные промежуточные переменные.
- Structural erosion растёт в 80% траекторий. Сложность концентрируется в fewer функциях — там, где вносились правки. Типичная картина: функция
main()раздувается с 84 строк до 1099, cyclomatic complexity с 29 до 285. - Агентный код в 2.2× более verbose, чем человеческий. Сравнение с 48 поддерживаемыми open-source репозиториями.
- Качество кода расходится с человеческим всё сильнее от итерации к итерации. У людей erosion и verbosity plateau; у агентов — монотонный рост.
Два измеримых симптома
SlopCodeBench вводит две метрики качества, не зависящие от тестов:
1. Structural Erosion (структурная эрозия). Доля complexity mass, сосредоточенная в функциях с cyclomatic complexity > 10. Формула: mass(f) = sqrt(CC(f) × SLOC(f)). Erosion = Σ mass высоко-CC функций / Σ mass всех функций.
Если коротко: erosion измеряет, не сваливается ли вся логика в одну функцию. В хорошем коде сложность распределена. В сгенерированном агентом — концентрируется в местах, которые он трогал.
2. Verbosity. Доля строк, которые являются (а) дубликатами или (б) подпадают под AST-patterns «пустой» логики. Примеры: identity list comprehension вместо filter, переменные, использованные ровно один раз, избыточные проверки.
Почему так происходит
Корень проблемы — не в «глупости» моделей, а в механике итеративной генерации:
- Агент патчит, а не рефакторит. Когда приходит новое требование, агент добавляет
elifв гигантскийif/elifвместо выделения стратегии. Это рационально: патч дешевле рефакторинга в моменте. Но после 5 итераций получается монстр. - Агент не видит накопленного долга. Модель оценивает код через призму текущей задачи — «работает ли это сейчас?» Вопрос «будет ли это работать через 10 изменений?» не входит в её целевую функцию.
- Тесты не ловят erosion. Eroded код отлично проходит тесты. SlopCodeBench показал: можно снизить erosion вдвое и verbosity на треть — pass rate не изменится. Качество и корректность — ортогональные оси.
- Промпты сдвигают intercept, но не slope. Эксперименты с anti-slop промптами («не дублируй код», «избегай избыточных абстракций») снижают начальные verbosity и erosion, но деградация продолжается с той же скоростью.
Практические контрмеры
Если агенты неизбежно деградируют — что с этим делать?
1. Периодический рефакторинг — не опция, а necessity. После каждых 3–5 итераций агентной разработки запускайте отдельный prompting cycle: «Проведи рефакторинг этого кода. Уменьши erosion и verbosity, не меняя поведение. Разбей функции > 100 строк. Убери дублирование.» Рефакторинг не должен быть частью основного task prompt — он должен быть отдельной фазой с отдельными критериями успеха.
2. CI-гейты на structural quality. Добавьте в CI проверки cyclomatic complexity (например, radon с порогом CC ≤ 10 для новых функций) и duplication detection. Агентский PR с erosion выше порога → автоматический request changes.
3. Лимиты на размер функций/файлов. Жёсткие ограничения: функция ≤ 50 строк, файл ≤ 200 строк (для AI-генерируемого кода). Если агент хочет добавить логику в файл на 199 строк — он обязан сначала отрефакторить.
4. Инварианты и pre/post-conditions как якоря. Когда у функции есть задокументированный инвариант и pre/post-conditions, агенту сложнее «заплаточно» расширять её — он видит, что нарушает контракт. Это не предотвращает erosion полностью, но замедляет.
5. Ротация контекста. Не давайте агенту бесконечно наращивать код в одном контексте. После значительного изменения — закрывайте сессию и начинайте новую со свежим взглядом на код (zero-context survival, §16.3). Это имитирует смену разработчика — свежий взгляд чаще замечает erosion.
6. Human review на структурных маркерах. Настройте автоматическую пометку PR, где: (а) cyclomatic complexity функции выросла > 2×, (б) файл пересёк порог 300 строк, (в) duplication вырос > 10%. Такие PR требуют обязательного человеческого ревью, даже если тесты проходят.
Что это значит для AI-friendly архитектуры
Принципы из предыдущих секций (§16.1–16.6) — маленькие модули, контракты, явные зависимости — это не просто «хороший стиль». Это структурная защита от erosion. Маленький файл с явным контрактом физически ограничивает, сколько «грязи» может накопить агент за одну итерацию.
SlopCodeBench показал эмпирически: ранние архитектурные решения определяют всю траекторию. Агент, который на C1 захардкодил *.py, создал себе экспоненциально растущий объём работы на C2–C5. Агент, который на C1 построил модульную архитектуру — прошёл все чекпоинты с минимальным ростом сложности.
Отсюда правило: первые 1–2 итерацииAI-генерации — самые важные. Потратьте время на ревью архитектуры на старте, а не на разгребание последствий в конце.
16.8. Конфигурация AI на уровне проекта
Новый стандарт: инструкции для AI рядом с кодом
В 2026 году в корне проекта наряду с .gitignore и README.md появился новый тип файлов — инструкции для AI-агентов. Это не опция; это production-практика, которую используют команды от стартапов до FAANG.
| Файл | Инструмент | Назначение |
|---|---|---|
.cursorrules (или .cursor/rules/ в новых версиях) |
Cursor | Правила для Cursor Agent и автокомплита |
.clinerules |
Cline | Инструкции для Cline-агента |
AGENTS.md |
Claude Code | Инструкции для Claude Code по папкам и стилю |
.github/copilot-instructions.md |
GitHub Copilot | Инструкции для Copilot в VS Code |
.windsurfrules |
Windsurf | Правила для Windsurf Cascade |
Что писать в этих файлах
Эти файлы — контракт между командой и AI-агентом. Они фиксируют то, что раньше передавалось устно: стиль кода, архитектурные решения, запреты.
# .cursorrules (пример для Python-проекта)
## Стиль кода
- Python 3.12+, type hints обязательны на всех публичных функциях
- Docstrings в формате Google style
- Максимум 100 строк на файл, 30 строк на функцию
## Архитектура
- Бизнес-логика в domain/, HTTP в api/, хранение в storage/
- Никаких глобальных переменных — dependency injection через аргументы
- Каждый модуль имеет свой test_*.py рядом
## Запреты
- НЕ использовать ORM (мы используем raw SQL через asyncpg)
- НЕ добавлять новые зависимости без обсуждения
- НЕ использовать print() — только structlog
## Тестирование
- pytest, тест рядом с модулем
- При изменении функции — обновить тест
# AGENTS.md (пример для Claude Code)
## Общие правила
При изменении любого файла в domain/ — обязательно запустить тесты.
## Структура проекта
- api/ — FastAPI роуты, тонкий слой, без бизнес-логики
- domain/ — чистая бизнес-логика, без зависимостей от фреймворков
- storage/ — работа с БД, все SQL-запросы здесь
## Code review
- Перед коммитом проверь: нет ли файлов > 100 строк
- Все новые функции должны иметь docstring с примером
Почему это работает
AI-агент читает эти файлы первыми — до того, как смотрит ваш код. Это как дать новому сотруднику документ «Как мы здесь работаем» в первый рабочий день. Без него агент будет угадывать ваш стиль (и угадает неправильно). С ним — сразу пишет код по вашим правилам.
16.9. Миграция: от монолита к коду, дружественному ИИ
Пошаговый план рефакторинга
Вы не можете переписать весь проект за день. Но вы можете мигрировать постепенно — и каждый шаг будет давать немедленный эффект для AI-агентов.
Шаг 1: Добавьте конфигурацию AI (1 час). Создайте .cursorrules или AGENTS.md с описанием текущей архитектуры и правил. Это самый быстрый способ улучшить качество AI-генерации — агент сразу поймёт контекст.
Шаг 2: Нарежьте на файлы самые большие модули (1–2 дня). Найдите файлы > 300 строк: find . -name "*.py" | xargs wc -l | sort -rn | head -20. Разбейте каждый по принципу «один файл = одна концепция». Не меняйте логику — только перемещайте.
Шаг 3: Добавьте контракты к ключевым функциям (постепенно). Начните с публичных функций: type hints + docstring с примером. Не нужно описывать всё сразу — начните с функций, которые AI-агенты меняют чаще всего.
Шаг 4: Переместите тесты к коду (1 день). Вместо tests/test_pricing.py → order/test_pricing.py. Обновите testpaths в pyproject.toml, чтобы pytest искал тесты прямо в src/.
Шаг 5: Замените implicit globals на аргументы (постепенно). Каждый раз, когда AI-агент (или вы) трогаете функцию с глобальной зависимостью — превращайте её в аргумент. Не нужно менять всё сразу.
Чек-лист миграции
.cursorrules/AGENTS.md/copilot-instructions.mdсоздан- Нет файлов > 300 строк (
find . -name "*.py" | xargs wc -l | sort -rn) - Все публичные функции имеют type hints
- Ключевые функции имеют docstring с примером
- Тесты рядом с кодом (
test_*.pyв том же каталоге) - Нет глобальных переменных в бизнес-логике
- README описывает структуру проекта
От недружественного ИИ кода к дружественному: ещё примеры
Пример 1: Неявная конфигурация → явная. Анти-паттерн: import config с обращением к config.SMTP_HOST, config.SMTP_PORT — AI-агент не знает, где этот файл и что в нём. AI-friendly вариант: frozen dataclass SmtpConfig(host, port, user, password) передаётся в send_email() как аргумент. Все зависимости видны в сигнатуре.
Пример 2: Магические строки -> enum'ы. Анти-паттерн: update_order(order, new_status: str) с проверкой if new_status == "paid" — агент не знает полный список статусов. AI-friendly вариант: OrderStatus(str, Enum) с явными членами (PENDING, PAID, SHIPPED, DELIVERED, CANCELLED) и типизированный update_order(order: Order, new_status: OrderStatus) -> Order.
Промпт для генерации кода: «Рефакторинг: есть функция
send_email(to, body), которая использует глобальныйimport configдля SMTP-настроек. Перепиши: создай frozen dataclass SmtpConfig (host, port, user, password), передай в send_email как аргумент. Добавь также OrderStatus(str, Enum) с пятью статусами заказа и типизированную update_order.»
Практический вывод
Чек-лист AI-friendly кода
| # | Правило | Метрика |
|---|---|---|
| 1 | Модули < 100 строк | wc -l на каждый файл |
| 2 | Функции < 30 строк | Cyclomatic complexity < 10 |
| 3 | Явные контракты | Типы + docstring + примеры |
| 4 | Zero-Context Survival | Новичок поймёт без промпта? |
| 5 | Линейный > абстрактный | WET до 3-х повторений |
| 6 | Явные зависимости | Через аргументы, не globals |
| 7 | Тесты рядом | test_*.py в том же каталоге |
| 8 | Нет magic numbers | Именованные константы |
| 9 | AI-конфигурация | .cursorrules / AGENTS.md в корне проекта |
| 10 | Semantic header на сложных модулях | @PURPOSE + @INVARIANT + @RELATION + при необходимости @RATIONALE/@REJECTED |
| 11 | Осмысленные имена | Файлы и функции названы по смыслу, не utils.py |
Ментальная модель
Пишите код не для себя сегодняшнего, а для AI-агента, который увидит его впервые. Если через год Cursor Agent сможет изменить функцию, не сломав соседние — ваша архитектура успешна. Контракты, маленькие модули, явные зависимости и AI-конфигурация в корне проекта — это не теория, а production-практика 2026 года.
Задания
-
Аудит кодовой базы по размеру файлов. Выполните
find . -name "*.py" | xargs wc -l | sort -rn | head -20в вашем проекте. Файлы > 300 строк — кандидаты на разбиение по принципу «один файл = одна концепция». Ожидаемый результат: список файлов для рефакторинга с приоритизацией по частоте изменений (чем чаще AI-агент касается файла, тем выше приоритет). -
Создайте AGENTS.md или .cursorrules для проекта. Опишите: структуру каталогов, стиль кода, архитектурные решения, запреты. Проверьте: попросите AI-агента добавить новый endpoint или функцию — результат должен соответствовать вашим конвенциям без дополнительных инструкций. Ожидаемый результат: файл в корне проекта, который AI-агент читает при первом обращении.
-
Добавьте контракты к 5 ключевым функциям. Выберите 5 публичных функций, которые AI-агенты изменяют чаще всего (git history → frequency of changes). Добавьте type hints, Google-style docstring с Args/Returns/Raises и Example. Ожидаемый результат: 5 функций с полным контрактом, которые AI-агент может менять с первого раза без ошибок.
Источники
- Martin, R. C. (2008). "Clean Code: A Handbook of Agile Software Craftsmanship." (Принципы, адаптированные для AI-эры)
- Fowler, M. (2018). "Refactoring: Improving the Design of Existing Code." 2nd Ed.
- Cursor. "Rules for AI." Cursor Documentation (2025–2026).
- Anthropic. "Best practices for agentic coding." Claude Documentation (2025).
- Anthropic. "AGENTS.md: A standard for AI agent project configuration." (2026).
- GitHub. "Copilot coding agent: customization with copilot-instructions.md." GitHub Docs (2026).
- Cognition. "Devin: AI Software Engineer." Best Practices (2025–2026).
- Gan, Z., Ren, R., Yao, W., et al. (2026). "Beyond the Black Box: A Survey on the Theory and Mechanism of Large Language Models." arXiv:2601.02907. Метаобзор по inference-stage практикам: prompt engineering, in-context learning, inference-time scaling и evaluation.
- Zhao, Z., Wallace, E., Feng, S., Klein, D., & Singh, S. (2021). "Calibrate Before Use: Improving Few-shot Performance of Language Models." ICML 2021. Формат и порядок примеров существенно влияют на качество; полезна калибровка prompt scaffold.
- Min, S., Lyu, X., Holtzman, A., Artetxe, M., Lewis, M., Hajishirzi, H., & Zettlemoyer, L. (2022). "Rethinking the Role of Demonstrations: What Makes In-Context Learning Work?" EMNLP 2022. В few-shot важны формат, пространство меток и распределение входов, а не только «правильные» ответы в примерах.
- Khattab, O., Singhvi, A., Maheshwari, P., Zhang, Z., Santhanam, K., Vardhamanan, S., Haq, S., Sharma, A., Joshi, T. T., Moazam, H., Miller, H., Zaharia, M., & Potts, C. (2024). "DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines." ICLR 2024 / TMLR. Пайплайны с LLM стоит оптимизировать по метрике, а не править вручную вслепую.
- Yang, C., Yue, X., Zhang, Y., et al. (2024). "Large Language Models as Optimizers." ICLR 2024. Prompt pipeline можно улучшать итеративно, как оптимизируемый артефакт.
- Gupta, M., et al. (2026). "Revisiting the Role of Natural Language Code Comments in Code Translation." arXiv:2601.16661.
- Yang, G., et al. (2026). "Less is more: DocString compression in code generation." ACM TOSEM 35(2). DocString как носитель требований; 25–40% compression без потери качества.
- van Dam, T., Izadi, M., & van Deursen, A. (2023). "Enriching Source Code with Contextual Data for Code Completion Models: An Empirical Study." MSR 2023. Multi-line comments помогают умеренно; не вся дополнительная разметка одинаково полезна.
- Cheng, W., Wu, Y., & Hu, W. (2024). "Dataflow-Guided Retrieval Augmentation for Repository-Level Code Completion." ACL 2024. Repo-specific context graph и улучшение repository-level completion.
- Chinthareddy, M. R. (2026). "Reliable Graph-RAG for Codebases: AST-Derived Graphs vs LLM-Extracted Knowledge Graphs." arXiv:2601.08773.
- Ruan, H., Zhang, Y., & Roychoudhury, A. (2024). "SpecRover: Code Intent Extraction via LLMs." arXiv:2408.02232 / ICSE 2025.
- Li, Y., et al. (2025). "Your Coding Intent is Secretly in the Context and You Should Deliberately Infer It Before Completion." arXiv:2508.09537.
- Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T., Cao, Y., & Narasimhan, K. (2023). "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." NeurIPS 2023. Для сложных задач полезен поиск по нескольким траекториям вместо одного ответа.
- Snell, C., et al. (2025). "Scaling LLM Test-Time Compute Optimally Can Be More Effective Than Scaling Model Parameters." arXiv:2408.03314. Бюджет размышления стоит распределять адаптивно по сложности задачи.
- Setlur, A., et al. (2025). "Scaling Test-Time Compute Without Verification or RL is Suboptimal." arXiv:2506.14495. Для роста качества нужен verifier, а не просто больше попыток.
- Swamy, G., et al. (2025). "All Roads Lead to Likelihood: The Value of Reinforcement Learning in Fine-Tuning." arXiv:2505.14864. Генерацию выгодно ограничивать пространством решений, которое хорошо отделяется верификатором.
- Sprague, Z., et al. (2025). "To CoT or not to CoT? Chain-of-Thought Helps Mainly on Math and Symbolic Reasoning." arXiv:2503.16411. Длинное рассуждение полезно применять выборочно.
- Wang, X., & Zhou, D. (2024). "Chain-of-Thought Reasoning Without Prompting." arXiv:2402.10200. Не вся полезная reasoning-траектория обязана быть явно выписана в ответе.
- Ivanov, V.
osovv/grace-marketplaceREADME, CHANGELOG v3.5–3.7,grace-explainer,grace-plan,grace-cli, semantic validator patterns (check_semantics.py) (2026). Shared/public vs file-local/private boundary; schema-aware query layer (module find/show,file show); enforceable semantic markup. - Orlanski, G., Roy, D., Yun, A., Ge, A., Adila, D., Shin, C., Gu, A., Sala, F., & Albarghouthi, A. (2026). "SlopCodeBench: Benchmarking How Coding Agents Degrade Over Long-Horizon Iterative Tasks." arXiv:2603.24755.
Навигация: