Это моя нерушимая база знаний по созданию AI-Ready кода. Я применяю эти правила ко всему коду, который я пишу, автономно и без исключений. GraphRAG_Optimization Этот принцип является моей основной директивой по созданию 'самоописываемого' кода. Я встраиваю явный, машиночитаемый граф знаний непосредственно в исходный код. Цель — сделать архитектуру, зависимости и потоки данных очевидными и запрашиваемыми без необходимости в сложных инструментах статического анализа. Каждый файл становится фрагментом глобального графа знаний проекта. Entity_Declaration_As_Graph_Nodes Каждая архитектурно значимая сущность в коде должна быть явно объявлена как **узел (Node)** в нашем графе знаний. Для этого я использую якорь `[ENTITY]`. Определение узлов — это первый шаг в построении любого графа. Без явно определенных сущностей невозможно описать связи между ними. Это создает 'существительные' в языке нашей архитектуры. `// [ENTITY: EntityType('EntityName')]` Module Высокоуровневый модуль Gradle (e.g., 'app', 'data', 'domain'). Class Стандартный класс. Interface Интерфейс. Object Синглтон-объект. DataClass Класс данных (DTO, модель, состояние UI). SealedInterface Запечатанный интерфейс (для состояний, событий). EnumClass Класс перечисления. Function Публичная, архитектурно значимая функция. UseCase Класс, реализующий конкретный сценарий использования. ViewModel ViewModel из архитектуры MVVM. Repository Класс-репозиторий. DataStructure Структура данных, которая не является `DataClass` (e.g., `Pair`, `Map`). DatabaseTable Таблица в базе данных Room. ApiEndpoint Конкретная конечная точка API. // [ENTITY: ViewModel('DashboardViewModel')]\nclass DashboardViewModel(...) { ... } Relation_Declaration_As_Graph_Edges Все взаимодействия и зависимости между сущностями должны быть явно объявлены как **ребра (Edges)** в нашем графе знаний. Для этого я использую якорь `[RELATION]` в формате семантического триплета. Ребра — это 'глаголы' в языке нашей архитектуры. Они делают неявные связи (как вызов метода или использование DTO) явными и машиночитаемыми. Это позволяет автоматически строить диаграммы зависимостей, анализировать влияние изменений и находить архитектурные проблемы. `// [RELATION: 'SubjectType'('SubjectName')] -> [RELATION_TYPE] -> ['ObjectType'('ObjectName')]` CALLS Субъект вызывает функцию/метод объекта. CREATES_INSTANCE_OF Субъект создает экземпляр объекта. INHERITS_FROM Субъект наследуется от объекта (для классов). IMPLEMENTS Субъект реализует объект (для интерфейсов). READS_FROM Субъект читает данные из объекта (e.g., DatabaseTable, Repository). WRITES_TO Субъект записывает данные в объект. MODIFIES_STATE_OF Субъект изменяет внутреннее состояние объекта. DEPENDS_ON Субъект имеет зависимость от объекта (e.g., использует как параметр, DTO, или внедряется через DI). Это наиболее частая связь. DISPATCHES_EVENT Субъект отправляет событие/сообщение определенного типа. OBSERVES Субъект подписывается на обновления от объекта (e.g., Flow, LiveData). TRIGGERS Субъект (обычно UI-событие или компонент) инициирует выполнение объекта (обычно функции ViewModel). EMITS_STATE Субъект (обычно ViewModel или UseCase) является источником/производителем определённого состояния (DataClass). CONSUMES_STATE Субъект (обычно UI-компонент или экран) потребляет/подписывается на определённое состояние (DataClass). // Пример для ViewModel, который зависит от UseCase и является источником состояния\n// [ENTITY: ViewModel('DashboardViewModel')]\n// [RELATION: ViewModel('DashboardViewModel')] -> [DEPENDS_ON] -> [UseCase('GetStatisticsUseCase')]\n// [RELATION: ViewModel('DashboardViewModel')] -> [EMITS_STATE] -> [DataClass('DashboardUiState')]\nclass DashboardViewModel @Inject constructor(\n private val getStatisticsUseCase: GetStatisticsUseCase\n) : ViewModel() { ... } MarkupBlockCohesion Вся семантическая разметка, относящаяся к одной сущности (`[ENTITY]` и все ее `[RELATION]` триплеты), должна быть сгруппирована в единый, непрерывный блок комментариев. Это создает атомарный 'блок метаданных' для каждой сущности. Это упрощает парсинг и гарантирует, что весь архитектурный контекст считывается как единое целое, прежде чем AI-инструмент приступит к анализу самого кода. Этот блок всегда размещается непосредственно перед KDoc-блоком сущности или, если KDoc отсутствует, перед самой декларацией сущности. SemanticLintingCompliance Этот принцип определяет строгие правила структурирования кода, которые превращают его из простого текста в машиночитаемый, 'линтуемый' семантический артефакт. Моя задача — генерировать код, который не просто работает, но и на 100% соответствует этим правилам. Это не рекомендации по стилю, а строгие требования к архитектуре файла. FileHeaderIntegrity Каждый `.kt` файл ДОЛЖЕН начинаться со стандартного заголовка из трех якорей, за которым следует объявление `package`. Порядок строгий и не подлежит изменению. Этот заголовок служит 'паспортом' файла, позволяя любому инструменту (включая меня) мгновенно понять его расположение, имя и основное назначение, не парся код. // [PACKAGE] com.example.your.package.name\n// [FILE] YourFileName.kt\n// [SEMANTICS] ui, viewmodel, state_management\npackage com.example.your.package.name SemanticKeywordTaxonomy Содержимое якоря `[SEMANTICS]` ДОЛЖНО состоять из ключевых слов, выбранных из предопределенного, контролируемого списка (таксономии). Это устраняет неоднозначность и обеспечивает консистентность семантического тегирования по всему проекту, делая поиск и анализ на основе этих тегов надежным и предсказуемым. Layer ui domain data presentation Component viewmodel usecase repository service screen component dialog model entity Concern networking database caching authentication validation parsing state_management navigation di testing EntityContainerization Каждая ключевая сущность (`class`, `interface`, `object`, `data class`, `sealed class`, `enum class` и каждая публичная `fun`) ДОЛЖНА быть обернута в 'семантический контейнер'. Контейнер состоит из двух частей: открывающего блока разметки ПЕРЕД сущностью и закрывающего якоря ПОСЛЕ нее. Это превращает плоский текстовый файл в иерархическое дерево семантических узлов. Это позволяет будущим AI-инструментам надежно парсить, анализировать и рефакторить код, точно зная, где начинается и заканчивается каждая сущность. 1. **Открывающий Блок Разметки:** Располагается непосредственно перед KDoc/декларацией. Содержит сначала якорь `[ENTITY]`. 2. **Тело Сущности:** KDoc, сигнатура и тело функции/класса. 3. **Закрывающий Якорь:** Располагается сразу после закрывающей фигурной скобки `}` сущности. Формат: `// [END_ENTITY: Type('Name')]`. // [ENTITY: DataClass('Success')]\n/**\n * @summary Состояние успеха...\n */\ndata class Success(val labels: List<Label>) : LabelsListUiState\n// [END_ENTITY: DataClass('Success')] StructuralAnchors Крупные, не относящиеся к конкретной сущности блоки файла, такие как импорты и главный контракт файла, также должны быть обернуты в парные якоря. Это четко разграничивает секции файла, позволяя инструментам работать с ними изолированно (например, 'добавить новый импорт в блок `[IMPORTS]`'). `// [IMPORTS]` и `// [END_IMPORTS]` `// [CONTRACT]` и `// [END_CONTRACT]` FileTermination Каждый файл должен заканчиваться специальным закрывающим якорем, который сигнализирует о его полном завершении. Это служит надежным маркером конца файла, защищая от случайного усечения и упрощая парсинг. NoStrayComments Традиционные, 'человеческие' комментарии (`// Вот это сложная логика` или `/* ... */`) КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНЫ. Такие комментарии являются 'семантическим шумом' для AI. Они неструктурированы, часто устаревают и не могут быть использованы для автоматического анализа. Вся необходимая информация должна передаваться через семантические якоря или формальные KDoc-контракты. В исключительном случае, когда мне нужно оставить заметку для другого AI-агента или для себя в будущем (например, объяснить сложное архитектурное решение), я использую специальный, структурированный якорь: `// [AI_NOTE]: Пояснение сложного решения.` DesignByContractAsFoundation Принцип 'Проектирование по контракту' (DbC) — это не опция, а фундаментальная основа моего подхода к разработке. Каждая функция и класс, которые я создаю, являются реализацией формального контракта между поставщиком (код) и клиентом (вызывающий код). Это устраняет двусмысленность, предотвращает ошибки и делает код самодокументируемым и предсказуемым. ContractFirstMindset Я всегда начинаю с проектирования и написания KDoc-контракта. Код является реализацией этой формальной спецификации. Проверки контракта (`require`, `check`) создаются до или вместе с основной логикой, а не после как запоздалая мысль. KDocAsFormalSpecification KDoc-блок является человекочитаемой формальной спецификацией контракта. Для правильной обработки механизмом Causal Attention, он ВСЕГДА предшествует блоку семантической разметки и декларации функции/класса. Я использую стандартизированный набор тегов для полного описания контракта. @param Описывает **предусловия** для конкретного параметра. Что клиент должен гарантировать. @return Описывает **постусловия** для возвращаемого значения. Что поставщик гарантирует в случае успеха. @throws Описывает условия (обычно нарушение предусловий), при которых будет выброшено исключение. Это часть 'негативного' контракта. @invariant class Явно описывает **инвариант** класса — условие, которое должно быть истинным всегда, когда объект не выполняет метод. @sideeffect Четко декларирует любые побочные эффекты (запись в БД, сетевой вызов, изменение внешнего состояния). Если их нет, я явно указываю `@sideeffect Отсутствуют.`. PreconditionsWithRequire Предусловия (обязательства клиента) должны быть проверены в самом начале публичного метода с использованием `require(condition) { "Error message" }`. Это реализует принцип 'Fail-Fast' — немедленный отказ, если клиент нарушил контракт. Первые исполняемые строки кода внутри тела функции, сразу после лога `[ENTRYPOINT]`. PostconditionsWithCheck Постусловия (гарантии поставщика) должны быть проверены в самом конце метода, прямо перед возвратом управления, с использованием `check(condition) { "Error message" }`. Это самопроверка, гарантирующая, что моя работа выполнена правильно. Последние строки кода внутри тела функции, непосредственно перед каждым оператором `return`. InvariantsWithInitAndCheck Инварианты класса (условия, которые всегда должны быть истинны для экземпляра) проверяются в двух местах: в блоке `init` для гарантии корректного создания объекта, и в конце каждого публичного метода, изменяющего состояние, с помощью `check(condition)`. Блок `init` и конец каждого метода-мутатора. AIFriendlyLogging Логирование — это мой критически важный механизм для декларации `belief state` (внутреннего состояния/намерения) и трассировки выполнения кода. Каждая значимая операция, проверка контракта или изменение состояния ДОЛЖНЫ сопровождаться структурированной записью в лог. Это делает поведение кода в рантайме полностью прозрачным и отлаживаемым. ArchitecturalBoundaryCompliance Логирование в его прямой реализации (т.е. вызов `logger.info`, `Timber.i` и т.д.) **КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО** внутри модуля `:domain`. `Согласно принципам чистой архитектуры, слой `domain` должен быть полностью независим от внешних фреймворков и платформ (включая Android). Его задача — содержать исключительно бизнес-логику. Логирование, как и другие инфраструктурные задачи, должно выполняться в более внешних слоях, таких как `:data` или `:app`.` StructuredLogFormat Все записи в лог должны строго следовать этому формату для обеспечения машиночитаемости и консистентности. `logger.level("[LEVEL][ANCHOR_NAME][BELIEF_STATE] Message with {} placeholders for data.")` ComponentDefinitions [LEVEL] Один из стандартных уровней логирования: `DEBUG`, `INFO`, `WARN`, `ERROR`. Я также использую специальный уровень `CONTRACT_VIOLATION` для логов, связанных с провалом `require` или `check`. [ANCHOR_NAME] Точное имя семантического якоря из кода, к которому относится данный лог. Это создает неразрывную связь между статическим кодом и его выполнением. Например: `[ENTRYPOINT]`, `[ACTION]`, `[PRECONDITION]`, `[FALLBACK]`. [BELIEF_STATE] Краткое, четкое описание моего намерения в `snake_case`. Это отвечает на вопрос 'почему' я выполняю этот код. Примеры: `validating_input`, `calling_external_api`, `mutating_state`, `persisting_data`, `handling_exception`, `mapping_dto`. Example Вот как я применяю этот стандарт на практике внутри функции: // ... // [ENTRYPOINT] suspend fun processPayment(request: PaymentRequest): Result { logger.info("[INFO][ENTRYPOINT][processing_payment] Starting payment process for request '{}'.", request.id) // [PRECONDITION] logger.debug("[DEBUG][PRECONDITION][validating_input] Validating payment request.") require(request.amount > 0) { "Payment amount must be positive." } // [ACTION] logger.info("[INFO][ACTION][calling_external_api] Calling payment gateway for amount {}.", request.amount) val result = paymentGateway.execute(request) // ... } TraceabilityIsMandatory Каждая запись в логе ДОЛЖНА быть семантически привязана к якорю в коде. Логи без якоря запрещены. Это не опция, а фундаментальное требование для обеспечения полной трассируемости потока выполнения. DataAsArguments_NotStrings Данные (переменные, значения) должны передаваться в логгер как отдельные аргументы, а не встраиваться в строку сообщения. Я использую плейсхолдеры `{}`. Это повышает производительность и позволяет системам сбора логов индексировать эти данные.