Full-stack SSOT Orchestrator — CLI для одновременной проверки согласованности 5 SSOT и генерации кода.

GitHub-репозиторий

Трещины вайб-кодинга

С распространением вайб-кодинга стали проявляться закономерности.

Просишь AI: «Сделай бронирование» — делает. «Добавь отмену» — добавляет. При добавлении пятой функции ломается вторая. Изменили схему API, но не обновили фронтенд. Добавили колонку в БД, но сервисный слой о ней не знает.

Причина проста: AI не может удержать в памяти весь код.

Что делают люди: обнаружив поломку, говорят AI «Исправь и это». Исправляет — ломается другое. «И это тоже исправь.» Цикл повторяется. Чем больше проект, тем длиннее цикл, и в какой-то момент приходит мысль: «Быстрее переписать с нуля».

Почему код разрастается

В коде смешаны две вещи.

Решения: что показывать, какой API вызывать, в каком порядке обрабатывать, что сохранять. Проводка: код, реализующий эти решения в конкретном фреймворке.

Допустим, мы создаём систему бронирования.

Решение: "При создании брони — найти комнату; если нет — 404, если есть — создать"

Это одно решение в одну строку разбрасывается по React-хукам, Go-обработчикам, SQL-запросам, API-схемам и Terraform-ресурсам. Каждое оборачивается в синтаксис своего фреймворка, обрастает обработкой ошибок и преобразованиями типов.

Из 100 000 строк кода решения занимают 12 500 строк. Остальные 87 500 — проводка.

Контекстное окно AI-агента конечно. При добавлении десятой функции он не помнит предыдущие девять — потому что не может прочитать 100 000 строк целиком.

Если выделить только решения — 12 500 строк. Это 55% контекста в 200K токенов. Размер, который AI может охватить за один раз.

5 SSOT

Fullend сопоставляет каждому из 5 слоёв программного обеспечения свой DSL. Каждый DSL становится единственным источником истины (SSOT) для своего слоя.

СлойDSLЧто декларирует
ЭкранSTML (HTML5 + data-*)Что показывать и что делать
API-контрактOpenAPI 3.xКакие запросы принимать и какие ответы возвращать
Поток сервисаSSaC (Go comment DSL)В каком порядке обрабатывать
Структура данныхSQL DDL + sqlcЧто хранить
ИнфраструктураTerraform HCLГде запускать

OpenAPI, SQL DDL и Terraform — отраслевые стандарты. Для экрана и потока сервиса соответствующих SSOT DSL не существовало. Решения фронтенда тонули в React-хуках, поток сервиса рассыпался по Go-обработчикам. Поэтому были спроектированы STML и SSaC — DSL, созданные в рамках этого проекта.

specs/
├── frontend/*.html        → STML
├── api/openapi.yaml       → OpenAPI 3.x
├── service/*.go           → SSaC
├── db/*.sql               → SQL DDL + sqlc queries
└── terraform/*.tf         → HCL

specs/ — источник истины. artifacts/ можно пересоздать в любой момент.

Индивидуальная валидация уже существует

Инструменты проверки для трёх слоёв уже есть.

  • sqlc проверяет согласованность DDL и запросов.
  • Валидатор OpenAPI проверяет корректность схемы.
  • Terraform проверяет синтаксис и зависимости HCL.

Для STML и SSaC также созданы встроенные валидаторы. SSaC проверяет внутреннюю согласованность потоков сервиса, STML — соответствие UI-деклараций и OpenAPI.

Каждый из 5 слоёв может быть проверен внутри себя. Проблемы возникают между ними.

Фронтенд отображает поле через data-bind="memo", но в схеме ответа API поля memo нет. SSaC вызывает @model Reservation.SoftDelete, но в sqlc-запросах метода SoftDelete нет. В OpenAPI объявлено x-sort: [created_at], но в DDL-таблице нет индекса на эту колонку.

Каждый инструмент видит только свой слой. Трещины между слоями остаются невидимыми.

Скрыть структуру

«Но ведь придётся учить 5 DSL?»

Да. Но структуру не обязательно показывать пользователю.

Если в системный промпт агента заранее заложить технический стек и правила SSOT, пользователю достаточно сказать «Сделай бронирование». Агент сам добавит эндпоинт в OpenAPI, создаст таблицу в DDL, объявит поток сервиса в SSaC, нарисует экран в STML и запустит fullend validate для проверки согласованности.

Пользователь видит только результат. Структуру потребляет агент, а не изучает пользователь.

Опыт вайб-кодинга остаётся прежним. Меняется одно: за кулисами ничего не ломается.

Роль Fullend

Fullend — это перекрёстный валидатор. Он не переизобретает отдельные инструменты. Он вызывает каждый из них и проверяет границы между слоями.

fullend validate specs/
✓ DDL          3 tables, 18 columns
✓ OpenAPI      7 endpoints
✓ SSaC         7 service functions
✓ STML         4 pages, 6 bindings
✓ Cross        0 mismatches

All SSOT sources are consistent.

Если хотя бы одна проверка не пройдена:

✓ DDL          3 tables, 18 columns
✓ OpenAPI      7 endpoints
✗ SSaC         CancelReservation
               @model Reservation.SoftDelete — method not found in sqlc queries
✗ Cross        1 mismatch

FAILED: Fix errors before codegen.

Если валидация пройдена — генерируется код.

fullend gen specs/ artifacts/

sqlc генерирует модели БД, oapi-codegen — типы API, SSaC — сервисные функции, STML — React-компоненты, а Fullend — связующий код между ними.

Правила перекрёстной валидации

Уникальная ценность Fullend — в перекрёстной валидации.

OpenAPI ↔ DDL

Объект проверкиПравило
x-sort.allowedСуществует ли колонка в таблице
x-filter.allowedСуществует ли колонка в таблице
x-include.allowedСвязана ли таблица через FK

SSaC ↔ DDL

Объект проверкиПравило
@model Model.MethodСуществует ли метод в sqlc-запросах
@result TypeСовпадает ли тип с производным от DDL-таблицы
@param имяМожет ли быть преобразован в колонку DDL

SSaC ↔ OpenAPI

Объект проверкиПравило
Имя функцииСовпадает ли с operationId
@param requestЕсть ли поле в схеме запроса
@result + responseЕсть ли поле в схеме ответа

STML ↔ SSaC — оба ссылаются на один и тот же operationId OpenAPI. Если обе проверки пройдены, соответствие API, вызываемого фронтендом, и API, обрабатываемого бэкендом, гарантируется автоматически.

Проектирование для агентов

Fullend спроектирован для AI-агентов.

Чтобы агент мог писать спецификации, ему нужно знать 10 типов последовательностей SSaC, 12 атрибутов data-* STML, расширения OpenAPI x- и правила именования. Для этого предоставляется руководство для AI объёмом около 350 строк. Его достаточно один раз добавить в системный промпт агента.

Цикл валидации после написания спецификации прост.

Рабочий процесс агента:
1. Изменить specs/
2. fullend validate specs/
3. Есть ошибки → исправить соответствующий SSOT → перейти к шагу 2
4. Ошибок 0 → fullend gen specs/ artifacts/

Не нужно понимать всю систему. Достаточно исправить то, на что указывает validate, — и согласованность восстанавливается. Умная модель попадает с первого раза, маленькая — с третьего. Результат одинаков.

Размер SSOT по масштабу

МасштабПримерSSOTКод реализацииДоля контекста
МалыйЗапись в салон~1 500 строк~10 000 строк~8%
СреднийУровня Jira, Notion~12 500 строк~100 000 строк~55%
КрупныйУровня Shopify~30 000 строк~300 000 строк~90%

При контексте в 200K токенов. Для среднего SaaS агент может прочитать всю архитектуру за один раз.

Превращение исключений в паттерны

То, что не укладывается в 10 типов последовательностей, уходит в call. То, что не выражается через data-*, уходит в custom.ts. Если эти аварийные выходы превышают 20% от целого, смысл структуризации размывается.

Однако исключение, будучи изолированным, становится наблюдаемым. Когда множество проектов будут структурированы через Fullend, в call и custom.ts проявятся повторяющиеся паттерны.

10 типов последовательностей SSaC тоже не были спроектированы заранее. Они сходились к десяти в результате наблюдения сотен сервисных функций. Тот же принцип повторится и с аварийными выходами. Часто встречающиеся паттерны call станут новыми типами последовательностей, а часто встречающиеся паттерны custom.ts — новыми атрибутами data-*.

Исключения не уменьшаются — из исключений вырастает структура.

Расширение технического стека

Сейчас Fullend привязан к Go + React + PostgreSQL + Terraform. Это намеренно. На стадии PoC важнее пройти один стек насквозь.

Однако 3 из 5 SSOT (OpenAPI, SQL DDL, Terraform) уже не зависят от языка. 10 типов последовательностей SSaC — паттерны, не привязанные к языку; они лишь выражены через Go-комментарии. STML — это атрибуты HTML5 data-*, не зависящие от фреймворка.

Расширение сводится к добавлению бэкенда кодогенерации. Логика валидации и правила перекрёстной проверки остаются прежними.

Связь с GEUL

5 DSL образуют SSOT программного обеспечения. SSOT — это структурированные данные. Структурированные данные — это граф. Граф можно закодировать в GEUL.

data-fetch="ListReservations" в STML — это связь между сущностями. @sequence get → @model → @guard → @response в SSaC — это последовательность событий. Определение эндпоинта в OpenAPI — это контракт. Всё это семантические структуры, выразимые через тройные рёбра, рёбра событий6 и узлы сущностей GEUL.

Способ, которым Fullend выполняет перекрёстную валидацию 5 DSL — символьное сопоставление, проверка типовой согласованности, контроль ссылочной целостности — основан на том же принципе, что и механическая верификация в потоке GEUL.

Лицензия

MIT — GitHub