Full-stack SSOT Orchestrator — CLI для одновременной проверки согласованности 5 SSOT и генерации кода.
Трещины вайб-кодинга
С распространением вайб-кодинга стали проявляться закономерности.
Просишь 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