Архитектурный контроль нужен, когда в проекте есть договорённости о зависимостях: например, интерфейс не должен обращаться к хранилищу напрямую, а доменная логика не должна импортировать HTTP-обработчики. Обычные тесты поведения могут оставаться зелёными после такого изменения. Здесь проверяется само направление связей между частями программы.
Руководство предназначено для разработчика, который описывает границы модулей, и инженера CI, который подключает проверку к выпуску. Для первого шага нужны знакомство с YAML и доступ к GoCPG.
На этой странице:
- Типы архитектурных проблем и примеры.
- 12 контрактов для проверки модели.
- 10 эвристических паттернов для ревью.
- Подготовка YAML и проверка применимости.
- Проверка проекта и внедрение.
Какие архитектурные проблемы можно обнаружить
В GoCPG есть 12 типов архитектурных контрактов: правил, которые сравнивают связи в коде с объявленной моделью. Отдельная библиотека сценария 11 содержит 10 эвристических паттернов для поиска подозрительных зависимостей. Это два разных набора: контракт проверяет конкретную договорённость команды, а эвристика помогает найти место для архитектурного ревью.
В примерах ниже A → B означает зависимость A от B. Выбранный тип связи
существенен: импорт, вызов и включение заголовка отвечают на разные вопросы.
Схемы и числа в этом разделе учебные; это ожидаемая интерпретация входных
данных, а не вывод выполненного анализа вашего проекта. Полный запускаемый
пример YAML и команд приведён дальше в руководстве.
12 типов архитектурных контрактов
| Проблема | Контракт | Что проверяется |
|---|---|---|
| Запрещённая зависимость | forbidden_dependency |
Связь от выбранного источника к запрещённой цели. |
| Зависимость вне разрешённого списка | allowed_dependencies |
Выход выбранного источника за закрытый список целей. |
| Отсутствующая обязательная зависимость | required_dependency |
Наличие связей с заданной кратностью. |
| Нарушение направления между слоями | layers |
Соответствие матрице разрешённых направлений. |
| Связь между независимыми группами | independence |
Зависимости между группами, выделенными по тегу. |
| Цикл зависимостей | acyclic |
Циклы в графе компонентов, включая заданную политику петель. |
| Обход публичного API | public_api_only |
Доступ потребителей только к объявленной публичной поверхности. |
| Доступ к защищённому компоненту | protected_component |
Принадлежность потребителя разрешённому списку. |
| Использование API чужим потребителем | exclusive_api |
Доступ к именованной поверхности только утверждённых потребителей. |
| Файл без компонента или с несколькими владельцами | exhaustive_classification |
Полная и однозначная классификация. |
| Метрика вне допустимого диапазона | metric_threshold |
Соответствие метрики условию команды. |
| Недостаточная разрешимость зависимостей | resolution_coverage |
Доля разрешённых связей и наличие требуемых возможностей языка. |
1. Прямая или транзитивная запрещённая зависимость
В интерфейсе появляется from storage.db import save_order. Если правило
запрещает прямые импорты ui → storage, эта связь создаёт находку
forbidden_dependency. Вариант ui → application → storage не нарушает
именно прямой запрет. Для запрета всей цепочки нужна reachability: transitive.
Исправление зависит от цели правила. При прямом запрете перенесите обращение к хранилищу в сервис приложения, оставив UI вызов сервиса. При транзитивном запрете такой перенос всё ещё сохраняет запрещённый путь: нужно пересмотреть зависимость или архитектурное решение, а затем повторить анализ.
2. Новая зависимость вне разрешённого списка
Для checkout разрешены только catalog и payments. Связи
checkout → catalog и checkout → payments допустимы, а новый вызов
checkout → analytics.internal выходит за список. Контракт
allowed_dependencies указывает на эту связь даже без отдельного запрета
для analytics.
Уберите прямой доступ, например передайте событие через уже разрешённый компонент. Расширять список следует только после принятого изменения модели; добавление очередной цели ради зелёного результата скрывает исходную проблему.
3. Обязательная связь отсутствует
Команда требует, чтобы каждый выбранный компонент задания зависел от
audit. У invoice_job есть invoice_job → audit, а у refund_job такой
связи нет. При required_dependency с quantifier: each_component
ожидается находка для refund_job.
Добавьте реальное обращение к аудиту и повторите проверку. Этот контракт
проверяет наличие зависимости; он не доказывает, что аудит вызывается при
каждом выполнении задания. Для такого поведения нужны отдельные тесты.
at_least_one требует хотя бы одну подходящую связь во всей выбранной группе,
а exactly_one — ровно одну пару компонентов; это другое требование.
4. Нижний слой вызывает верхний
Матрица разрешает ui → application и application → storage, но не
storage → ui. Вызов уведомления интерфейса из репозитория данных создаёт
нарушение layers. Разрешённые направления задаются явно через
may_depend_on; имена каталогов сами по себе матрицу не определяют.
Верните результат операции из Storage и обработайте его в Application или UI.
Если нужны связи внутри одного слоя, задайте их явно в матрице или через
allow_same_layer.
5. Независимые подсистемы знают друг о друге
Компоненты помечены scope: billing и scope: shipping и должны развиваться
независимо. Вызов billing.invoice → shipping.internal_labels пересекает
группы. Контракт independence с группировкой по тегу scope выявляет
эту связь; разрешённые исключения задаются отдельно.
Вынесите общий контракт данных в согласованную общую часть или организуйте взаимодействие через утверждённую границу. Повторный запуск должен показать, что прямой зависимости между независимыми группами больше нет.
6. Компоненты образуют цикл
Связи orders → payments → notifications → orders образуют цикл длиной три.
Контракт acyclic проверяет граф компонентов и возвращает свидетельства
цикла. Отдельно задаётся, считать ли петлю orders → orders нарушением.
Например, перенесите общий тип события из Orders в отдельный Contracts, чтобы Notifications зависел от Contracts. Проверьте, что замкнутый путь исчез, а не только сменил имя. Эвристический детектор взаимных вызовов, описанный ниже, имеет более узкие условия и не заменяет этот контракт.
7. Потребитель обходит публичный API
Billing публикует billing.api.issue_invoice, а billing.internal.reprice
остаётся внутренним. Вызов checkout → billing.internal.reprice нарушает
public_api_only, если Checkout выбран потребителем, а Billing — целью.
Вызов объявленного billing.api.issue_invoice допустим при той же модели.
Используйте публичную операцию либо согласуйте изменение публичной поверхности.
Наличие слова internal в пути только поясняет пример: фактическая проверка
опирается на объявление API и данные графа.
8. Чужой компонент получает доступ к защищённой части
payment_keys разрешён только компоненту payment_worker. Связь
admin_panel → payment_keys нарушает protected_component, даже если
вызываемая операция технически экспортируется. Здесь ограничен круг
потребителей целого компонента.
Передайте запрос через утверждённую операцию Payment Worker. Этот контроль зависимостей не заменяет проверку прав доступа во время выполнения.
9. Специальный API используется не своим потребителем
У Payments две именованные поверхности: charge и settlement.
Поверхность settlement разрешена только settlement_worker. Вызов
checkout → payments.settlement нарушает exclusive_api; публичность
операции не даёт Checkout разрешение на её использование.
Checkout должен обращаться к своей операции charge. В отличие от
protected_component, ограничение относится к одной именованной поверхности.
Опция prohibit_other_surfaces_for_allowed_consumers дополнительно запрещает
утверждённому потребителю использовать другие поверхности этого компонента.
10. Код не попадает в модель или попадает сразу в две группы
Модель описывает только src/ui/** и src/storage/**, но в производственный
код добавлен src/jobs/refund.py. Контракт exhaustive_classification
показывает неклассифицированную сущность. Если же src/ui/refund.py
одновременно совпадает с селекторами UI и Shared, он показывает конфликт.
Добавьте компонент Jobs или уточните пересекающиеся селекторы. Проверяйте
полноту классификации отдельно от зависимостей: отсутствие находок по импортам
не подтверждает, что новый каталог вообще участвовал в проверке. Неполная
классификация может блокировать выпуск как BLOCKED_INCOMPLETE.
11. Компонент слишком связан или слишком велик
Команда задаёт fan_out <= 5, но Orders зависит от семи разных внешних
компонентов. Контракт metric_threshold возвращает значение 7 и порог 5.
Семь вызовов одного компонента не равны семи зависимым компонентам:
GoCPG считает уникальные внешние цели для этой метрики.
Сократите число самостоятельных обязанностей Orders и повторите измерение.
Порог 5 здесь учебный, а не универсальная норма. Контракт также поддерживает
fan_in, instability, transitive_dependency_count, relative_visibility,
used_public_api_ratio, public_api_size, cycle_participation,
component_loc и component_symbol_count. Возможность измерения и входные
данные выбранной метрики должны быть подтверждены для запуска.
12. Анализ не может разрешить достаточно связей
В учебном графе Python есть 100 учитываемых прямых связей, из которых 80
имеют состояние resolved или resolved_multiple. При
minimum_coverage: 0.95 контракт resolution_coverage получает долю 0,8
и фиксирует недостаточное покрытие. В динамически формируемом импорте
importlib.import_module(module_name) цель может остаться неизвестной.
Проверьте подготовку графа, доступность нужных возможностей анализатора и способ разрешения динамических связей. Отсутствующая возможность или неизвестный знаменатель блокируют достоверный вывод. Пустой граф не означает покрытие 100 %. Не устраняйте такую проблему простым снижением порога: сначала установите, какие связи остались вне доказанного анализа.
10 эвристических паттернов сценария 11
Эти проверки используют вызовы и метрики CPG. Результат — кандидат на ревью: он не всегда означает нарушение архитектурного решения. Ниже приведены условия запросов текущей библиотеки; словесное название паттерна может быть шире того, что фактически измеряет запрос.
| Паттерн | Пример входных связей и условие сигнала | Что проверить и как исправить |
|---|---|---|
Взаимная зависимость, CIRCULAR_DEPS |
orders.py → payments.py и payments.py → orders.py. Запрос ищет взаимные вызовы пары разных файлов. |
Вынести общий контракт или инвертировать зависимость. Цикл из трёх файлов без взаимной пары этим запросом не подтверждается; используйте acyclic. |
Нарушение слоёв, LAYER_VIOLATION |
Метод из Storage вызывает Core или Network; либо Core вызывает Network. Слои выводятся из настроенных шаблонов имён файлов. | Сначала проверить отнесение файлов к слоям, затем убрать обратный вызов. Для собственной матрицы слоёв используйте layers. |
Модуль с чрезмерными зависимостями, GOD_MODULE |
У manager.py 21 различное имя вызываемого метода: fan_out > 20. Альтернативное условие: более 30 различных имён вызывающих методов (fan_in > 30). Эти показатели отличаются от компонентных метрик GoCPG. |
Проверить смешение обязанностей и разделить модуль. Высокий входящий показатель у стабильного общего API может быть допустимым. |
Стабильный модуль зависит от нестабильного, UNSTABLE_DEPS |
core.py → experiment.py; для Core I = 2 / (18 + 2) = 0,1, для Experiment I = 9 / (1 + 9) = 0,9. Запрос требует I_source < 0.3 и I_target > 0.7. |
Ввести абстракцию и передавать реализацию извне. Здесь I = fan_out / (fan_in + fan_out); это структура зависимостей, а не частота Git-изменений. |
Чужая ответственность в методе, FEATURE_ENVY |
report.generate содержит шесть записей вызова методов из customer.py. Условие: более пяти вызовов из одного метода в другой файл. |
Перенести сбор данных к Customer или дать ему одну подходящую операцию. Запрос не сравнивает доступ к своим и чужим полям; повторные вызовы тоже учитываются. |
Слишком тесная взаимная связь, INAPPROPRIATE_INTIMACY |
A содержит шесть вызовов B, B — пять вызовов A: есть оба направления, суммарно больше десяти. | Сократить протокол взаимодействия и убрать знание внутренних деталей. Сам запрос считает вызовы, а не доказывает доступ к приватным данным. |
Зависимости файлов, FILE_INCLUDE_DEPS |
Функция из ui.c вызывает внутреннюю функцию из db.c. Запрос группирует вызовы между разными файлами; достаточно одной различной вызываемой функции. |
Это карта связей для ревью, а не автоматический запрет. Проверить, соответствует ли связь модели. Несмотря на имя, запрос читает edges_call, а не директивы #include. |
Взаимные связи файлов, CIRCULAR_INCLUDE_DEPS |
a.c → b.c и b.c → a.c по вызовам функций. |
Разорвать взаимную зависимость и пересобрать граф. Запрос использует вызовы; один только взаимный #include без вызовов этим результатом не доказывается. |
Файл, от которого зависит много других, HUB_HEADERS |
Функции из common.c вызываются из десяти разных файлов; условие caller_file_count >= 10. |
Проверить смешение обязанностей, разделить API по назначению. Запрос считает файлы-потребители вызовов, а не число включений заголовка и не время перекомпиляции. |
Связность каталогов, MODULE_INCLUDE_ISOLATION |
Между frontend и backend есть пять разных пар файлов с вызовами; условие file_pair_count >= 5. |
Проверить ожидаемые границы и публичные точки взаимодействия. Запрос выделяет первый сегмент пути по обратной косой черте и читает вызовы; для путей с / или иной структуры каталогов интерпретацию нужно проверить отдельно. |
Пороговые сигналы не являются нормативом для каждого проекта. Например, центральный модуль логирования может иметь много потребителей по замыслу, а связь UI с Storage может быть нарушением уже при одном вызове. Для принятой командой границы задайте явный контракт; эвристики используйте при исследовании и выборе мест для его внедрения.
Подробности 12 контрактов и полей правил приведены в справочнике модели и DSL. Порядок запуска архитектурного ревью описан в руководстве по сценарию 11.
Пример и ожидаемый результат
Рассмотрим Python-проект с двумя каталогами: src/ui/ содержит код интерфейса,
src/storage/ — доступ к данным. Мы хотим запретить прямой импорт из UI в
Storage. Для реального приложения между ними обычно выделяют сервисный слой;
в первом правиле достаточно описать две проверяемые границы.
Компонент — группа файлов или символов. Модель задаёт эти группы, правило задаёт разрешённые отношения между ними. CPG хранит обнаруженные в коде связи. Нарушение (finding) должно указывать на конкретную связь и место в исходнике. Решение о выпуске (release gate) дополнительно зависит от полноты анализа, принятого долга и утверждённых исключений.
Подготовка правила и проверка исходников — разные этапы. Ниже можно воспроизвести
первый: проверить YAML, применимость правила к Python и описание компонента.
architecture validate не читает исходники и не строит CPG. Даже результат
applicable: true не означает, что в проекте нет нарушений.
Подготовка окружения
Используйте сборку GoCPG, в которой есть gocpg architecture --help.
Если команда отсутствует, установленный бинарный файл не поддерживает этот
раздел. В дереве исходников текущую версию можно собрать из каталога gocpg:
go build -o ./bin/gocpg ./cmd/gocpg
Версия Go указана в gocpg/go.mod. Добавьте каталог бинарного файла в PATH
или заменяйте gocpg полным путём к нему. Проверка YAML не требует локального
сервера CodeGraph или базы проекта. Для чтения сохранённых находок через
explain нужна сборка с CGO/DuckDB.
Следующие команды запускаются из корня репозитория. Файл
gocpg/docs/examples/architecture-control/architecture.yaml входит в исходники.
Его полное содержимое приведено ниже; пример не требует дописывать скрытые поля.
Модель и первое правило
У правила стабильный идентификатор example.ui-no-storage. У компонентов
отдельные uid: сохраняйте их при переименовании читаемого id, чтобы
сравнение результатов не воспринимало компонент как новый.
Селектор paths выбирает файлы относительно корня анализируемого проекта.
components выбирает уже объявленные компоненты по идентификаторам.
import — тип ребра, а imports — название требуемой возможности анализатора;
это разные поля с разными значениями.
spec_version: "2.0"
kind: architecture
id: example.ui-no-storage
version: "1"
fingerprint_version: 1
languages: [python]
architecture:
source_roots:
- path: src
source_set: production
classification:
exhaustive: true
conflict_policy: error
unclassified_policy: error
generated_policy: ignore
minimum_coverage: 1.0
components:
- uid: cmp-example-ui
id: ui
name: UI
kind: leaf
match:
paths: ["src/ui/**"]
- uid: cmp-example-storage
id: storage
name: Storage
kind: leaf
match:
paths: ["src/storage/**"]
contract: forbidden_dependency
from:
components: [cmp-example-ui]
to:
components: [cmp-example-storage]
relation:
edge_types: [import]
reachability: direct
languages: [python]
required_capabilities: [imports, source_sets]
minimum_coverage: 1.0
source_roots определяет производственный код. Требование полной и однозначной
классификации означает: каждый файл в этой области должен попасть в компонент. Перед блокирующей
проверкой устраните конфликты селекторов и определите долю покрытия.
В этом небольшом примере других производственных каталогов нет.
forbidden_dependency запрещает связи от from к to.
reachability: direct проверяет непосредственный импорт. Если задача —
запретить достижимость через промежуточные компоненты, потребуется транзитивное
правило; менять этот смысл незаметно для существующего baseline нельзя.
Проверка применимости
gocpg architecture validate --file gocpg/docs/examples/architecture-control/architecture.yaml --language python --json
В JSON проверьте следующие поля; остальные поля ответа здесь опущены:
{
"rule_id": "example.ui-no-storage",
"applicable": true,
"gate_evaluated": false,
"reason_codes": ["applicable"]
}
applicable подтверждает совместимость правила с объявленными возможностями
языка. Поле gate_evaluated: false сообщает, что решения о выпуске ещё нет.
Для неподходящего языка, например --language c, команда может завершиться
с кодом 0, но вернуть applicable: false и language_not_selected.
Поэтому одной проверки exit code в CI недостаточно: нужно читать JSON.
Синтаксическая ошибка, неизвестное поле YAML, отсутствующий файл или неверный
CLI-флаг приводят к ненулевому коду завершения. Для этой группы команд нужны
--file и --json; флаги --rule и --format json не поддерживаются.
Проверка описания компонента
gocpg architecture describe --file gocpg/docs/examples/architecture-control/architecture.yaml --component ui --json
В ответе ожидаются rule_id: example.ui-no-storage,
component.uid: cmp-example-ui и component.id: ui.
Если запрошенный компонент отсутствует, команда завершится ошибкой.
Проверьте, что прочитана нужная модель, прежде чем искать нарушение в графе.
describe возвращает объявление компонента, его родителя и непосредственных
детей. Оно не показывает фактическую классификацию файлов: исходники этой
командой не читаются.
От правила к проверке проекта
Архитектурный анализ запускается через ci-update. Передайте policy, ключ
проекта, release control и путь к артефакту. Policy задаёт компоненты,
классификацию и правила; release control задаёт профиль проверки выпуска.
Пройдите учебный запуск с готовыми входами:
он содержит исходники Python, оба файла конфигурации, подготовку Git и команды
построения CPG. Затем выполните пример с нарушением и объяснением.
В нём прямой импорт создаёт сохранённую находку, а explain показывает правило,
компоненты и строку исходника. Это полный путь от конфигурации до результата.
Для интеграции используйте run_id из результата и fingerprint из находки.
Сохранённый результат также содержит ревизию исходников, выполненные правила
и полноту анализа. Команды validate и describe помогают проверить модель
перед запуском, а explain читает результат после него.
Как внедрять без ложного зелёного статуса
- Зафиксируйте компоненты и классификацию; проверьте список неклассифицированных сущностей и конфликтов селекторов.
- Закрепите точные версии языкового набора и набора правил. Для блокирующего
режима используйте конкретную версию вместо
latest. - Запустите профиль
discovery. Его результат помогает настроить модель; решение о выпуске принимает блокирующая проверка. - Перейдите в
advisory, разберите ложные срабатывания и сформируйте baseline только для осознанно принятого долга. - Оформляйте временное исключение как waiver с владельцем, согласующим, причиной, ссылкой на решение и сроком действия.
- Включите
enforce_new, когда CPG свежий, все активные правила выполнены, а классификация, разрешение связей и покрытие возможностей подтверждены. - Используйте
enforce_allилиstrictтолько после устранения известного долга либо утверждения решений по нему.
Статусы discovery и advisory дают NOT_APPLICABLE, а не разрешение на
выпуск. В блокирующих профилях только PASS означает release_allowed=true.
Нарушения дают FAIL_VIOLATIONS; устаревший CPG, неполный запуск, неизвестный
знаменатель покрытия, отсутствующая возможность или непроверенный манифест дают
BLOCKED_INCOMPLETE.
Baseline, waiver и доверие
Базовый набор (baseline) хранит известную находку, версию её отпечатка
(fingerprint) и хеш смысла правила. При изменении смысла правила решение
получает статус needs_review: команда должна повторно его рассмотреть.
В профиле enforce_new принятое решение по базовому набору исключает известную
находку из числа новых нарушений. Само наличие локального файла этого не делает.
Временное исключение (waiver) действует для одной находки в указанной области. Переименование символа или новый отпечаток требуют отдельного решения. Просроченные, отозванные и неиспользуемые исключения отражаются в результате.
Доверенный манифест управления связывает решение с проектом, репозиторием, коммитом, хешами модели и правил, сроком действия и возрастающей ревизией. Управляющий контур или CI поставляет ключи доверия и сведения об их отзыве.
Полный и инкрементальный запуск
Результат incremental_complete должен совпадать с полным запуском: по набору
отпечатков находок, состояниям базового набора и исключений, а также сводному
хешу смысла результата. Изменения модели, публичного API, базового набора,
исключений, рёбер зависимостей или сильно связных компонентов расширяют область
повторного анализа. При неполном результате блокирующая проверка выполняет одну
синхронную полную попытку. Неполный итог получает статус BLOCKED_INCOMPLETE.
GoCPG сначала публикует подготовленные изменения файлов, затем сверяет связанные
семантические данные с доверенным перечнем исходников. Статус clean означает,
что проверены устаревшие поколения, рёбра без существующих концов, индексы,
состояние графа и охваченные производные строки. Физическое уплотнение хранилища
запускается отдельно. Подробный контракт приведён в
разделе об инкрементальном сканировании.
Диагностика результата
gocpg architecture describe --file gocpg/docs/examples/architecture-control/architecture.yaml --component ui --json
gocpg architecture explain --db ./cpg.duckdb --run-id RUN --fingerprint SHA256 --json
describe показывает компонент с родителем и непосредственными детьми.
explain читает сохранённую каноническую находку, её места в исходниках
и путь связи. Обе команды читают данные и сохраняют исходный результат анализа.
Руководство и три подробных справочника
Сначала пройдите сценарий выше. Затем откройте модель и правила, чтобы описать архитектуру, запуск и управление, чтобы проверить проект, и интерфейсы и результаты, чтобы разобрать вывод. В трёх справочниках размещены все 17 нормативных тем; карта ниже помогает найти нужную тему и сохраняет прежние ссылки.
Карта 17 тем
1. Модель архитектуры. Опишите корни исходников, компоненты, стабильные uid,
иерархию и классификацию. Результат этого шага — однозначное владение файлами и
символами.
2. DSL правил. Запишите kind: architecture, контракт, селекторы, языки,
возможности анализатора и покрытие. Различайте тип ребра CPG import и возможность
imports.
3. Каталог контрактов. Выберите один из 12 контрактов: зависимости, слои, циклы, API, полнота классификации, метрика или доля разрешённых связей.
4. Реестр capabilities. Проверьте, какие факты действительно поставляет
языковой анализатор. Статус complete подтверждает обязательные семейства фактов.
Для блокирующей проверки они требуются и при статусе degraded.
5. Создание preset. Добавьте стабильный id@version, перечень возможностей
и тестовые исходники с ожидаемыми результатами. Каждый пример проверяет работу
правила на реальном исходном файле.
6. Каталог presets. Выбирайте preset по точному ID и семантической версии.
Блокирующая проверка требует закреплённой версии и набора для выбранного языка;
latest и псевдоним соседнего языка не подходят.
7. Baseline. Зафиксируйте известную находку по версии отпечатка, хешу смысла правила и точной области. Изменение смысла правила требует ревью.
8. Waiver и доверие. Исключение действует для одной находки в течение указанного срока. Манифест управления связывает коммит, хеши модели и правил, область, ревизию, подпись и сведения об отзыве ключа.
9. Профили release gate. discovery и advisory помогают настроить модель;
enforce_new, enforce_all и strict могут блокировать выпуск. Решение должно
быть PASS, FAIL_VIOLATIONS или BLOCKED_INCOMPLETE с понятной причиной.
10. Инкрементальное сканирование. Повторное использование допустимо только при совпадении отпечатков, сводного хеша смысла результата и состояний базового набора и исключений. Изменения модели, публичного API, ребра или сильно связного компонента расширяют область повторного анализа.
11. Миграция. Находки прежней системы сначала используются для исследования или параллельного сравнения. Блокирующий режим включается после сравнения результатов в течение двух циклов выпуска.
12. CLI. validate проверяет применимость, describe показывает модель,
explain читает сохранённую каноническую находку. Решение о выпуске принимает
проверка, которая учитывает результат и полноту анализа.
13. gRPC. Клиент выбирает базу через db и сохранённый запуск через
run_id. Для объяснения одной находки дополнительно передайте её fingerprint.
Ответ содержит ревизию исходников, идентичность находки и полноту анализа.
14. JSON Schema. Используйте схемы для обмена результатами, а не как замену описанию процесса. Проверяйте обязательные поля идентичности запуска, исхода, полноты, места в исходнике и жизненного цикла.
15. SARIF. Экспорт сохраняет ID правила, отпечаток, состояние находки,
места в исходниках и подтверждающие данные. Каждая находка получает уровень
error. Передавайте SARIF в Code Scanning, а решение о выпуске читайте
из канонического результата.
16. Mermaid и PlantUML. Диаграмма показывает модель и связи для ревью. Она отображает сохранённые находки и помогает проверить направление зависимостей.
17. Диагностика. Начинайте со статуса и кода причины. Обновите устаревший CPG, определите знаменатель покрытия, восстановите обязательные возможности, разрешите связи или подтвердите манифест. Затем повторите блокирующую проверку.
Навигация по темам:
- Архитектурная модель
- DSL архитектурных правил
- Каталог контрактов
- Реестр capabilities
- Создание presets
- Каталог presets
- Baseline
- Waiver и модель доверия
- Профили release gate
- Инкрементальное сканирование
- Миграция
- CLI
- gRPC
- JSON Schema
- Сопоставление SARIF
- Экспорт Mermaid и PlantUML
- Диагностика
Подробные поля, схемы, ссылки на исходники и технические проверки находятся в трёх справочниках выше. Это руководство содержит рабочий маршрут и карту тем.
Сейчас каталог v1 содержит три общих шаблона и одиннадцать языковых наборов: 1С, C, C++, C#, Go, Java, JavaScript, Kotlin, PHP, Python и TypeScript. Для каждого языка отдельно проверяются возможности анализатора и результаты тестовых примеров.
Совместимость и восстановление
Канонические результаты хранятся в gocpg_architecture_results. Таблица
cpg_architecture_result_heads указывает на текущий результат. Миграционный реестр
architecture_adoption_ledger.v1 хранит вывод прежней системы как явно
помеченные данные исследования или параллельного сравнения;
legacy_enforcement_allowed=false. Для перехода к блокирующему режиму сравните
результаты в течение двух циклов выпуска (two_release_cycles).
Подробности построения графа и восстановления типов приведены в техническом разборе GoCPG, а пользовательский сценарий — в анализе архитектуры.
Сквозной сценарий принятия решения
В репозитории есть минимальное правило
gocpg/docs/examples/architecture-control/architecture.yaml. Оно показывает
границы UI и Storage и запрещает прямую зависимость. Сценарий состоит из пяти
проверяемых шагов.
- Проверить правило. Выполните
validateи убедитесь, чтоapplicable=true,gate_evaluated=false, аreason_codesсодержитapplicable. Это проверка входной конфигурации, не результат аудита. - Проверить модель. Выполните
describe --component uiи проверьте стабильныйcmp-example-ui. Описание компонента помогает понять, к какой границе относится последующая находка. - Построить CPG. Для отдельного Python-проекта используйте
gocpg parse --input ./example-project --output ./cpg.duckdb --lang python. Для PR с историей используйтеgocpg ci-update --input . --output cpg.duckdb --base-ref origin/main --head-ref HEAD --json. Проверьте в результате ревизию и полноту построения. - Оценить policy. Подключите архитектурный анализ к
ci-updateи передайте четыре поля: policy, ключ проекта, release control и путь к артефакту. Выбранная policy задаёт корни исходников, компоненты, правила и классификацию.validateпроверяет входную конфигурацию. Анализ выполняет команда обновления CPG; отдельная командаarchitecture evaluateв CLI не заявлена. - Разобрать находку и исправить исходник. Из канонического результата
возьмите
run_idи отпечаток находки, затем выполнитеexplain. После исправления повторите полный или допустимый инкрементальный запуск. Неподтверждённая полнота, обязательная возможность или знаменатель покрытия дают статусBLOCKED_INCOMPLETE.
CI-фрагмент только для CPG
Выполняйте команды из корня анализируемого Git-репозитория. До первого инкрементального обновления создайте CPG для того же каталога и языка:
gocpg parse --input . --output cpg.duckdb --lang python
GoCPG сохраняет область разбора и текущую Git-ревизию в базе. Убедитесь, что
разбор завершился без ошибок и создан cpg.duckdb. Затем обновляйте эту же
базу командой ниже. Репозиторий должен содержать ссылки origin/main и HEAD.
В JSON ожидаются success: true, base_commit и head_commit; при совпадении
ревизий число изменённых файлов равно нулю.
gocpg ci-update --input . --output cpg.duckdb --base-ref origin/main --head-ref HEAD --lang python --json
Без архитектурных полей команда только обновляет CPG. Чтобы запросить архитектурный анализ, передайте все четыре поля:
Следующая команда служит шаблоном интеграции, а не полным упражнением UI/Storage. Замените
config/architecture-policy.yaml и config/architecture-release-control.yaml существующими,
проверенными файлами внутри анализируемого репозитория, задайте ключ проекта и создайте
каталог артефакта. Небольшой architecture.yaml выше содержит правило, а не полный набор настроек
policy или release control. Подготовьте эти входы по справочнику выполнения перед запуском шаблона.
gocpg ci-update --input . --output cpg.duckdb --base-ref origin/main --head-ref HEAD --lang python --json `
--architecture-policy config/architecture-policy.yaml `
--architecture-project-key inventory-service `
--architecture-release-control config/architecture-release-control.yaml `
--architecture-artifact artifacts/architecture-control.json
gocpg architecture validate --file gocpg/docs/examples/architecture-control/architecture.yaml --language python --json
gocpg architecture describe --file gocpg/docs/examples/architecture-control/architecture.yaml --component ui --json
CI проверяет JSON и артефакт архитектурного анализа вместе с кодом возврата. У validate для
неподходящего языка возможен код 0 при applicable=false; это диагностический
результат, не разрешение на выпуск. Если отсутствуют все четыре архитектурных
поля, policy не запрошена. Неполный набор полей завершается ошибкой. Полный набор
запускает выбранную policy; отсутствующий, повреждённый, небезопасный или внешний
по отношению к репозиторию входной файл вызывает ошибку проверки.
Что считается исправлением
Исправление проверяется новым запуском для изменённой ревизии. Сравните находки, выполненные правила, полноту и итоговый статус.
В проверенном учебном продолжении
форматирование переносится в greet, и прямой импорт исчезает. После пересборки
графа finding_count меняется с 1 на 0, а результат функции сохраняется.
В этом минимальном проекте удаляется единственная связь. Поэтому проверка
покрытия возвращает BLOCKED_INCOMPLETE с причиной canonical_coverage_incomplete.
Так результат отдельно показывает устранение находки и состояние покрытия.
Как выбирать следующий раздел
Если проблема в файлах без владельца, переходите к модели и DSL. Если правило уже нарушается, смотрите контракты, baseline и waiver. Если находки различаются между полным и PR-запуском, проверяйте инкрементальную семантику и capabilities. Если результат нужно передать в CI или Code Scanning, используйте JSON/SARIF и SARIF, сохраняя канонический результат как источник решения.