archispec
v0.2.0
Published
ArchiSpec CLI: валидация архитектурных постановок и визуализация архитектуры.
Maintainers
Readme
ArchiSpec
CLI-утилита archispec для работы с архитектурными постановками (proposals) и детальной архитектурой. Методология — spec driven development с акцентом на архитектуру.
Статус публикации: пакет archispec подготовлен к публикации в npm и будет опубликован в ближайшем релизе (ARCHLNT-0007). CLI публикуется под именем archispec. До публикации CLI можно запустить из исходников — см. раздел «Разработка». Ниже везде используется имя archispec.
Команды
archispec init [dir] --agent <name> # создать скелет .archi/ + установить skill для AI-агента (MVP: pi)
archispec proposal new <name> # создать новый proposal по шаблону
archispec proposal validate <path> # полная проверка proposal: схема + валидность результата гипотетического merge
archispec proposal merge <path> # применить JSON Patch к architecture/index.yaml, перенести в archive/
archispec architecture validate # валидировать architecture/index.yaml по index.schema.json
archispec architecture view # отрендерить визуальное представление (PlantUML или Markdown)
archispec generate <input> # legacy-обёртка над architecture view (PlantUML)archispec init [dir] --agent <name>
Инициализирует структуру .archi/ в целевой директории (по умолчанию — CWD) и дополнительно устанавливает skill-пакет ArchiSpec для указанного AI-агента.
BREAKING (с install-agent-skills): опция --agent <name> обязательна. Без неё init завершается с exit code 2 и подсказкой. Ранее init работал без опций.
archispec init --agent pi # создать .archi/ + skill для агента pi
archispec init ./my-proj --agent piСоздаваемая структура:
.archi/
├── proposals/
│ └── prop-NNNN/ # создаётся при `archispec proposal new`
│ └── proposal.yaml
├── architecture/
│ └── index.yaml
└── archive/ # создаётся лениво при первом `archispec proposal merge`
# (после успешного merge proposal переносится сюда)
.pi/ # только при --agent pi
├── skills/archispec/
│ ├── SKILL.md
│ └── references/{schemas.md, json-patch.md}
└── prompts/archi-{explore,proposal,apply,validate,merge,view}.mdindex.yaml — минимальный, валидный по schemas/index.schema.json. Содержит architecture.context.system с пустым services/exposes и пустой массив architecture.context.externals: [] — это нужно, чтобы proposal могли добавлять внешние системы через add с -. Skill-пакет — побайтово идентичен эталону из npm-пакета. Опция --force дозаписывает недостающие файлы в .archi/ и перезаписывает файлы skill-пакета эталоном (без --force модифицированные пользователем файлы не трогаются — выдаётся warning).
constitution.md — опциональный файл архитектурных инвариантов (вне создания init). Связь с архитектурой — через поле metadata.constitution_ref в architecture/index.yaml и/или proposal.yaml. Содержимое и формат constitution.md в v1 не валидируются схемами (планируется в v2).
MVP: только pi. Другие агенты (claude, opencode) пока не поддерживаются — см. раздел «Что не вошло». Эталоны skill-пакета живут в agents/ в npm-пакете.
archispec proposal new <name>
Создаёт .archi/proposals/prop-NNNN/proposal.yaml по минимальному шаблону. Нумерация продолжается от максимального существующего prop-NNNN (минимум 4 цифры). Поддерживает --title и повторяемый --author.
archispec proposal validate <path>
Выполняет полную проверку архитектурной постановки: (1) валидация proposal по schemas/proposal.schema.json; (2) применение proposal.change к копии текущей архитектуры в памяти и валидация результата — схема index.schema.json плюс семантические правила (уникальность id, цели depends_on/required/facade_on). Все нарушения собираются в один список. Если архитектура недоступна или невалидна, выполняется только проверка схемы (с предупреждением). Ничего не записывает. Коды возврата см. в разделе «Exit-коды».
archispec proposal merge <path>
Применяет операции из proposal.change (JSON Patch, RFC 6902) к architecture/index.yaml. Перед записью валидирует proposal, текущую архитектуру и результат (схема + семантическая валидация со сбором всех нарушений); после успешного merge обновляет proposal.metadata.status = merged и переносит proposal в .archi/archive/prop-NNNN/. Поддерживает --dry-run для проверки без записи.
Известные ограничения v1:
- JSON Pointer для массивов поддерживает селектор по
id(/architecture/services/{id: weaver}/required/-) — расширение ArchiSpec поверх RFC 6901. Резолв выполняется против текущего состояния документа для каждой операции. Числовые индексы (/architecture/services/0/required/-) тоже работают. Строки с{}в YAML должны быть обёрнуты в кавычки. - Чтобы
addчерез-работал, целевой массив должен уже существовать в документе (см. разделarchispec init— какие массивы создаются по умолчанию).
archispec architecture validate [path]
Валидирует architecture/index.yaml по schemas/index.schema.json. По умолчанию — .archi/architecture/index.yaml.
archispec architecture view [path]
Рендерит визуальное представление архитектуры:
-s, --section <name>(по умолчаниюcontext) — раздел архитектуры:context,services,data,apis.--format puml(по умолчанию) — PlantUML-диаграмма в stdout или в файл через--out. Все диаграммы начинаются с препроцессорной директивы!pragma layout elk— раскладка через Eclipse Layout Kernel, стабильная локально и на любом PlantUML-сервере.--format markdown— Markdown с YAML-таблицами, секциями и PlantUML-диаграммой внутри markdown code-fence (НЕ Mermaid). PlantUML-блок байт-в-байт идентичен--format puml(включая pragma-директиву).--no-validate— пропустить валидацию по JSON Schema.--no-legend— не добавлять legend-блок (применимо для обоих форматов; для markdown легенда по умолчанию включается).
Разделы: context — система и внешние зависимости; services — внутренние компоненты внутри контейнера rectangle <<System>> (источник — context.system.services, резолвнутые в architecture.services); data — ER-модель (architecture.data.entities); apis — публичные контракты и связи facade_on. Пустые/отсутствующие services/data/apis дают осмысленный пустой результат; нерезолвимые ссылки (ResolutionError) возвращают код 1.
Exit-коды
Сводная таблица для всех команд CLI:
| Код | Значение | Где встречается |
|-----|----------|-----------------|
| 0 | Успех. | Все команды. |
| 1 | Структурная ошибка: схема не выполнена, JSON Patch неприменим, нерезолвимая ссылка, существующий .archi/ без --force и т.п. | Все команды кроме init (для init см. код 2 ниже). |
| 2 | Ошибка использования или ввода-вывода: отсутствует обязательный --agent (в init), неподдерживаемый агент, файл не найден, не парсится. | init (без --agent или с неизвестным агентом); остальные команды при IO-ошибках. |
Процесс разработки
archispec init archispec proposal new foo
│ │
▼ ▼
┌─────────┐ change ┌────────────┐
│ .archi/ │ ◀─────────────────│ proposals/ │
│ │ JSON Patch │ prop-NNNN │
│ arch/ │ │ draft │
│ index │ └─────┬──────┘
└─────────┘ │
▲ ▼
│ archispec proposal validate
│ │
│ ▼
│ (errors? → fix)
│ │
│ ▼
│ archispec proposal merge prop-NNNN
│ │
│ ▼
│ apply change ┌────────────┐
└────────────────────────│ index.yaml │
│ updated │
└────────────┘
│
▼
move → archive/
status: mergedДетальная архитектура
Детальная архитектура в v1-MVP описывается одним плоским файлом architecture/index.yaml:
- Контекст — система, внешние зависимости, контракты (верхний уровень: что система предоставляет наружу и от кого зависит). Рендерится через
--section context. - Сервисы — внутренние компоненты системы и их связи: рендерится через
--section services(компоненты внутри контейнераrectangle <<System>>, exposes/required). - Данные — ERM: рендерится через
--section data(сущности, атрибуты, ref-связи). - Публичные API — OpenAPI/OpenRPC/AsyncAPI/GraphQL и связи
facade_on: рендерится через--section apis.
Разделение на отдельные файлы (components.yaml, data.yaml, apis.yaml) отнесено в v2.
Схема architecture/index.yaml (краткая сводка)
Полная документация — в schemas/README.md. Здесь — компактные таблицы для навигации.
Верхний уровень:
| Поле | Тип | Обязательно |
|------|-----|-------------|
| metadata | объект | да |
| metadata.name | Identifier (kebab-case) | да |
| metadata.version | SemVer | да |
| metadata.constitution_ref | string (путь к constitution.md) | нет |
| architecture | объект | да |
| architecture.context | объект | да |
| architecture.services | массив Component | да |
| architecture.data | DataModel | нет |
| architecture.apis | массив ContractRef | нет |
architecture.context.system — система как единица контекста:
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| id | Identifier | да | Идентификатор системы (kebab-case). |
| name | string | нет | Человекочитаемое имя. |
| services | массив Reference | да | Список id сервисов, из которых состоит система. Допустимы строки или [{id: ...}]. |
| exposes | массив ContractRef | да | Публичные контракты системы. |
| depends_on | массив Reference | нет | Внешние зависимости (только id из externals[*].id). |
architecture.context.externals[] — внешние системы:
| Поле | Тип | Обязательно |
|------|-----|-------------|
| id | Identifier | да |
| name | string | да |
| exposes | массив ContractRef | да |
architecture.services[] (Component) — сервисы/компоненты:
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| id | Identifier | да | Уникальный id компонента. |
| name | string | нет | Человекочитаемое имя. |
| owner | string | нет | Команда/роль, ответственная за компонент. |
| required | массив Reference | нет | Идентификаторы контрактов, потребляемых компонентом (связь только через контракты). |
| exposes | массив ContractRef | да | Контракты, предоставляемые компонентом. |
| code_paths | массив string | нет | Пути в кодовой базе (для drift detection). |
В depends_on, required и services (как массив ссылок) допускается смешивание форм: строка-id или объект {id: ...} (определение — _shared.schema.json#/$defs/Reference). Все идентификаторы сущностей документа (система, сервисы, внешние системы, контракты, сущности данных) глобально уникальны; уникальность и целостность ссылок проверяются семантической валидацией при proposal validate и proposal merge.
architecture.data (DataModel) — ERM (опционально):
| Поле | Тип | Описание |
|------|-----|----------|
| entities[] | массив Entity | Сущности данных. |
| entities[].id | Identifier | Идентификатор сущности. |
| entities[].description | string | Описание. |
| entities[].attributes[] | массив Attribute | Атрибуты (минимум 1). |
| attributes[].name | Identifier | Имя атрибута. |
| attributes[].type | string | Один из: string \| int \| uuid \| bool \| datetime \| ref:<entity-id> \| json. |
| attributes[].required | bool (default true) | Обязательность. |
| attributes[].description | string | Описание. |
architecture.apis[] и ContractRef:
Публичные API верхнего уровня. Каждый элемент — ContractRef, переиспользуемый в System.exposes, External.exposes, Component.exposes.
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| id | Identifier | да | Уникальный id контракта. |
| format | enum | да | openapi \| openrpc \| graphql \| asyncapi \| plaintext. |
| stack | Stack | да | Сетевой стек (см. ниже). |
| version | string | нет | Версия контракта. |
| facade_on | массив Identifier | нет | Id внутренних контрактов, на которые строится фасад (anti-corruption layer). |
| ref | string | нет | Путь к файлу контракта относительно architecture/. |
Stack (формат сетевого стека): URI-подобная строка. Примеры: /tcp/http, /tcp, /ip/udp, /ip/udp/quic. Точный паттерн — в _shared.schema.json#/$defs/Stack.
Схема proposal (краткая сводка)
Верхний уровень proposal.yaml:
| Поле | Тип | Обязательно |
|------|-----|-------------|
| metadata | объект | да |
| targets | объект (поля опциональны, но объект обязателен) | да |
| change | массив JSON Patch (RFC 6902), минимум 1 операция | да |
| adr | MADR-подобный объект | нет |
| implementation | объект | нет |
proposal.metadata:
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| id | ProposalId (prop-NNNN) | да | Формат id proposal. |
| title | string (5–120) | да | Краткое название. |
| status | Status | да | Состояние в жизненном цикле (см. ниже). |
| authors | массив string (≥1) | да | Авторы. |
| reviewers | массив string | нет | Ревьюверы. |
| created_at | date-time | да | ISO 8601 / RFC 3339. |
| updated_at | date-time | нет | Дата обновления. |
| superseded_by | ProposalId | нет | Id proposal, заменившего данный. |
| related_adrs | массив string | нет | Связанные ADR. |
| related_issues | массив string | нет | Связанные issues. |
| related_prs | массив string | нет | Связанные PR. |
| related_proposals | массив ProposalId | нет | Связанные proposal. |
| tags | массив string | нет | Теги. |
| constitution_ref | string | нет | Путь к constitution.md. |
proposal.targets — какие сущности архитектуры затрагивает proposal (все поля опциональны):
| Поле | Тип | Описание |
|------|-----|----------|
| components | массив Identifier | Затрагиваемые компоненты (architecture.services[].id). |
| apis | массив Identifier | Затрагиваемые контракты. |
| data_entities | массив Identifier | Затрагиваемые сущности данных. |
| externals | массив Identifier | Затрагиваемые внешние системы. |
Кросс-валидация targets ↔ architecture/index.yaml не выполняется схемой (запланировано в v2).
proposal.change (JSON Patch, RFC 6902):
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| op | enum | да | add \| remove \| replace \| move \| copy. |
| path | JSON Pointer | да | Куда применить. Суффикс - — append в массив. |
| value | any | для add/replace | Что вставить / чем заменить. |
| from | JSON Pointer | для move/copy | Откуда взять значение. |
Поддерживается селектор по id для массивов: /architecture/services/{id: weaver}/required/- — расширение ArchiSpec поверх RFC 6901. Числовые индексы (/architecture/services/0/required/-) тоже работают.
proposal.adr (опционально, MADR-подобный нарратив):
| Поле | Тип | Обязательно | Описание |
|------|-----|-------------|----------|
| problem | string | да | Какую проблему решает proposal. |
| motivation | string | да | Обоснование выбранного решения. |
| decision | string | да | Что именно выбрано. |
| consequences | массив string (≥1) | да | Последствия. |
| rollback_plan | string | нет | План отката. |
| breaking | bool (default false) | нет | Является ли изменение breaking. |
proposal.implementation (опционально):
| Поле | Тип | Описание |
|------|-----|----------|
| code_paths | массив string | Пути в коде. |
| pr_refs | массив string | Ссылки на PR. |
Жизненный цикл proposal
Состояния metadata.status (расширение MADR):
| Состояние | Когда | Что делает CLI |
|-----------|-------|----------------|
| draft | Proposal создан через archispec proposal new. | Создаётся в этом состоянии. |
| proposed | Выставлен на ревью. | Выставляется вручную в proposal.yaml. |
| accepted | Одобрен ревью, готов к merge. | Можно вызывать archispec proposal merge. |
| rejected | Отклонён ревью. | Перенос в archive/ опционально. |
| superseded | Заменён другим proposal (поле superseded_by). | Перенос в archive/. |
| deprecated | Больше не актуален. | Перенос в archive/. |
| merged | Успешно слит с детальной архитектурой. | archispec proposal merge переносит в archive/ и выставляет merged. |
Переходы proposed → accepted | rejected | superseded в v1 выполняются вручную (правка metadata.status); полная автоматизация workflow — в v2.
Что вошло в v1-MVP
archispec init(с--agent <name>) /proposal new|validate|merge/architecture validate|view/generate(legacy aliasarchispec architecture view --format puml).- Установка skill-пакета для агента
pi:SKILL.md+ 6 slash-команд/archi-*+references/. - JSON Patch через
fast-json-patchсvalidate=true, mutate=false. - Атомарная запись через
tmp+fs.rename. - Markdown-рендер с PlantUML-блоком внутри code-fence для GitHub/GitLab (Mermaid не используется).
- PlantUML/Markdown-рендер всех секций: контекст, сервисы, данные, публичные контракты.
- Тесты: 106 unit/integration-тестов.
Что не вошло в v1 (отложено в v2)
archispec completion— bash/zsh completion.- Генерация заготовок контрактов (OpenAPI/AsyncAPI scaffolds).
- Кросс-валидация ссылок (
proposal.targets.*↔architecture/index.yaml). - Разделённое хранение архитектуры (
components.yaml,data.yaml,apis.yaml). - Поддержка
--agent claudeи--agent opencodeвarchispec init. В MVP поддерживается толькоpi. Причина: Claude Code не обнаруживает.agents/skills/нативно, а общего стандарта для slash-команд в.agents/нет (у каждого агента свой путь и frontmatter). Реализация требует дублирования эталона в нативные директории с разными frontmatter — заведено в бэклог. - Поддержка алиасов id в JSON Pointer (нужен собственный резолвер).
Разработка
Требования к окружению:
- Node.js ≥ 20 — для dev-инструментов (eslint, vitest, тип-чек).
- Bun ≥ 1.1.0 — для запуска собранного CLI (
bin/archispec) и для сборочного скриптаscripts/build.ts.
Установка зависимостей:
npm installСборка CLI:
npm run buildКоманда внутри вызывает bun run scripts/build.ts, который через Bun.build() собирает src/cli.ts в dist/archi.cjs (CommonJS, shebang #!/usr/bin/env bun, права 0o755). Собранный бинарь становится доступен в node_modules/.bin/archispec после npm install через поле bin в package.json.
Запуск собранного CLI:
./dist/archi.cjs --version
./dist/archi.cjs architecture view path/to/index.yaml --format markdownПолная верификация (тип-чек → lint → тесты → сборка):
npm run verifyСхемы
Детальная архитектура и proposal описываются JSON Schema (Draft 2020-12). Схемы лежат в schemas/ и покрывают:
schemas/_shared.schema.json— общие определения:Identifier,ProposalId,SemVer,Status,ContractFormat,Stack,ContractRef,Reference,JsonPointer.schemas/index.schema.json— корневой файл архитектуры (architecture/index.yaml).schemas/proposal.schema.json— архитектурная постановка (proposals/prop-NNNN/proposal.yaml).
Полная документация — в schemas/README.md.
Интеграция с OpenSpec: схема architecture-driven
OpenSpec управляет требованиями (capability-спеки, delta-merge, AI-skills), а ArchiSpec — детальной архитектурой (architecture/index.yaml, JSON Patch). Это ортогональные слои, поэтому они не конкурируют, а дополняют друг друга. Точка интеграции — кастомная OpenSpec-схема openspec/schemas/architecture-driven/ (candidate в Community Schemas OpenSpec, по образцу superpowers-bridge).
Схема расширяет дефолтную spec-driven, переиспользуя ядерные артефакты (proposal, specs, design, tasks) и добавляя нишевый артефакт architecture-change:
proposal (почему)
├→ architecture-change.yaml (что меняется в архитектуре — JSON Patch RFC 6902)
└→ specs (что система должна делать — delta-требования)
└→ design (как — ссылается и на specs, и на architecture-change)
└→ tasks (реализация)Apply-фаза вызывает archispec CLI: PRECHECK наличия на PATH → archispec proposal validate → archispec proposal merge в .archi/architecture/index.yaml. Без CLI apply останавливается с явной ошибкой (без silent fallback).
Языковая конвенция. Нарратив схемы (описания, инструкции, комментарии в шаблонах) — на русском; английскими остаются YAML-ключи, валидаторо-проверяемые заголовки (## Why, ## ADDED Requirements, ### Requirement:, #### Scenario:, WHEN/THEN/SHALL/MUST), команды CLI и технические термины (JSON Patch, RFC 6902, PRECHECK, targets, components, data_entities и т.д.). Это соответствует AGENTS.md и не ломает openspec validate.
Использование:
openspec new change <name> --schema architecture-driven
openspec schemas # убедиться, что схема видна
openspec schema validate architecture-drivenИзвестное ограничение: archispec proposal merge после применения патча переносит proposal в .archi/archive/. Чтобы не перемещать авторский файл из смены, apply копирует architecture-change.yaml в .archi/proposals/prop-NNNN/proposal.yaml и merge'ит копию. Полное устранение — флаг --no-archive в CLI (в бэклоге).
Детали дизайна — в смене openspec/changes/add-architecture-driven-schema/.
См. также
AGENTS.md— процесс работы (постановка → реализация → синхронизация), язык документации, разделение ответственности междуAGENTS.mdиREADME.md..backlog/— задачи проекта (Backlog.md). Содержит активные задачи, напримерARCHLNT-0001(синхронизацияschemas/иsrc/schemas/),ARCHLNT-0004(поддержка--agent claude/--agent opencode).openspec/— архитектурные изменения (OpenSpec). Каталогopenspec/specs/содержит текущие спеки возможностей (capability),openspec/changes/— завершённые, текущие и архивные смены.
Лицензия и changelog
Проект распространяется под лицензией MIT — см. LICENSE.
История изменений — в CHANGELOG.md.
Рабочий пример проекта с proposal и архитектурой — в 001-simple/ (architecture/index.yaml + proposals/0001-add-cache.yaml).
