Install
$ agentstack add skill-itsalt-nacl-nacl-sa-architect ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
/nacl-sa-architect --- Архитектурная декомпозиция (Graph)
Назначение
Декомпозиция информационной системы на функциональные модули (Bounded Contexts), определение межмодульных зависимостей и высокоуровневых нефункциональных требований. Все данные читаются из Neo4j графа (BA-подграф) и записываются в Neo4j граф (SA-подграф).
Shared References
Read nacl-core/SKILL.md for:
- Neo4j MCP tool names and connection info (
mcp__neo4j__read-cypher,mcp__neo4j__write-cypher) - ID generation rules
- Schema files location (
graph-infra/schema/sa-schema.cypher) - Query library location (
graph-infra/queries/)
Key Schema (SA Layer)
From graph-infra/schema/sa-schema.cypher:
| Node | Key Properties | Description | |------|---------------|-------------| | Module | id, name, description, ucrangestart, ucrangeend | Functional module (Bounded Context) | | Requirement | id, description, type, priority | Functional or non-functional requirement |
Key SA relationships used by this skill:
(:Module)-[:CONTAINS_UC]->(:UseCase)--- module owns a use case(:Module)-[:CONTAINS_ENTITY]->(:DomainEntity)--- module owns a domain entity(:Module)-[:DEPENDS_ON {type, description}]->(:Module)--- inter-module dependency(:ProcessGroup)-[:SUGGESTS]->(:Module)--- BA-to-SA handoff edge
Режимы работы
Режим full (по умолчанию)
Полная декомпозиция системы с нуля: 5 фаз интерактивного диалога.
Когда: Новый проект, Module узлы ещё не созданы в графе.
Режим module
Добавление одного модуля в существующую архитектуру.
Когда: Модули уже существуют в графе, нужно расширить.
Параметр: module_name --- имя нового модуля (snake_case).
Workflow
+----------+ +----------+ +----------+ +----------+ +-----------+ +----------+
| Phase 0 | | Phase 1 | | Phase 2 | | Phase 3 | | Phase 3.5 | | Phase 4 |
| BA Ctx |--->| Бизнес- |--->| Модули |--->| Context |--->| External |--->| NFR и |
| Import | | контекст | | (в граф) | | Map | | Contracts | | constr. |
| (граф) | | | | | | (в граф) | | (артефакт | | (граф) |
| | | | | | | | | + граф) | | |
+----------+ +----------+ +----------+ +----------+ +-----------+ +----------+
Каждая фаза завершается:
- Резюме --- что понято
- Подтверждение --- запрос верификации у пользователя
- Артефакт --- создание/обновление узлов и рёбер в Neo4j графе
Не переходи к следующей фазе без явного подтверждения пользователя!
Предварительная проверка
Режим full
- Проверь наличие Module узлов в графе:
// mcp__neo4j__read-cypher
MATCH (m:Module) RETURN count(m) AS module_count
Если module_count > 0 --- предупреди о возможной перезаписи.
- Проверь наличие BA-данных в графе:
// mcp__neo4j__read-cypher
MATCH (gpr:ProcessGroup) RETURN count(gpr) AS pg_count
Если pg_count = 0 --- предупреди, что BA-подграф пуст; Phase 0 будет пропущена.
Режим module
- Загрузи существующие модули:
// mcp__neo4j__read-cypher
MATCH (m:Module)
RETURN m.id AS id, m.name AS name, m.uc_range_start AS uc_start, m.uc_range_end AS uc_end
ORDER BY m.uc_range_start
Если модулей нет --- предложи /nacl-sa-architect в режиме full.
- Определи занятые имена и диапазоны UC.
- Определи свободный диапазон UC для нового модуля.
Phase 0: Импорт BA-контекста из графа
Цель: Прочитать BA-подграф и извлечь контекст для архитектурного проектирования.
Шаг 0.1: Загрузить все ProcessGroup и их BusinessProcess
// mcp__neo4j__read-cypher
MATCH (gpr:ProcessGroup)-[:CONTAINS]->(bp:BusinessProcess)
RETURN gpr.id AS gpr_id, gpr.name AS gpr_name,
collect({id: bp.id, name: bp.name, description: bp.description}) AS processes
Шаг 0.2: Загрузить все BusinessEntity (бизнес-объекты)
// mcp__neo4j__read-cypher
MATCH (be:BusinessEntity)
OPTIONAL MATCH (be)-[:HAS_ATTRIBUTE]->(a:EntityAttribute)
RETURN be.id AS id, be.name AS name, be.type AS type, be.description AS description,
collect({id: a.id, name: a.name, data_type: a.data_type}) AS attributes
Шаг 0.3: Загрузить automation scope (шаги для автоматизации)
// mcp__neo4j__read-cypher
MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws:WorkflowStep {stereotype: "Автоматизируется"})
OPTIONAL MATCH (ws)-[:PERFORMED_BY]->(r:BusinessRole)
RETURN bp.id AS bp_id, bp.name AS bp_name,
ws.id AS ws_id, ws.function_name AS ws_function,
r.full_name AS role_name
ORDER BY bp.id, ws.step_number
Шаг 0.4: Загрузить существующие предложения по модулям (если есть)
// mcp__neo4j__read-cypher
MATCH (gpr:ProcessGroup)-[:SUGGESTS]->(m:Module)
RETURN gpr.id AS gpr_id, gpr.name AS gpr_name,
m.id AS module_id, m.name AS module_name
Шаг 0.5: Загрузить бизнес-роли
// mcp__neo4j__read-cypher
MATCH (r:BusinessRole)
OPTIONAL MATCH (r)-[:OWNS]->(owned:BusinessProcess)
OPTIONAL MATCH (r)-[:PARTICIPATES_IN]->(part:BusinessProcess)
RETURN r.id AS id, r.full_name AS name,
collect(DISTINCT owned.name) AS owns_processes,
collect(DISTINCT part.name) AS participates_in
Шаг 0.6: Загрузить бизнес-правила
// mcp__neo4j__read-cypher
MATCH (brq:BusinessRule)
OPTIONAL MATCH (brq)-[:CONSTRAINS]->(be:BusinessEntity)
OPTIONAL MATCH (brq)-[:APPLIES_IN]->(bp:BusinessProcess)
RETURN brq.id AS id, brq.name AS name, brq.description AS description,
collect(DISTINCT be.name) AS constrains_entities,
collect(DISTINCT bp.name) AS applies_in_processes
Вывод Phase 0
Покажи пользователю сводку:
**Phase 0: Импорт BA-контекста из графа**
BA-подграф загружен:
- Группы процессов: {N} (содержат {M} бизнес-процессов)
- Бизнес-объекты: {N}
- Шаги для автоматизации: {N} (из {M} бизнес-процессов)
- Бизнес-роли: {N}
- Бизнес-правила: {N}
- Предложения по модулям: {N} (из SUGGESTS-рёбер)
Эти данные будут использованы как основа для проектирования.
Переходим к Phase 1 для верификации и уточнения.
Если BA-подграф пуст
Пропусти Phase 0, перейди к Phase 1. Работай в стандартном режиме --- собирай всю информацию от пользователя.
Phase 1: Бизнес-контекст
Цель: Верифицировать и уточнить бизнес-контекст на основе BA-данных из графа.
Если BA-данные загружены (Phase 0 выполнена)
Предложи пользователю верификацию, а не задавай вопросы с нуля:
На основе BA-подграфа я вижу:
**Бизнес-процессы:** {список процессов по группам}
**Scope автоматизации:** {N} шагов подлежат автоматизации
**Ключевые объекты:** {список бизнес-объектов}
**Роли:** {список ролей}
Вопросы для уточнения:
1. Все ли процессы должны быть покрыты системой?
2. Есть ли внешние системы для интеграции, не отражённые в графе?
3. Есть ли ограничения scope, которые нужно учесть?
Если BA-данных нет
Задавай вопросы как в стандартном sa-architect:
- Какую бизнес-задачу решает система?
- Кто целевые пользователи?
- Какие основные функциональные области?
- Что НЕ входит в scope?
- Есть ли внешние системы для интеграции?
Действия после получения ответов
- Сформулируй бизнес-цели (2--3 пункта)
- Определи success criteria
- Опиши scope (что входит, что не входит)
- Опиши целевых пользователей на основе BusinessRole из графа
Артефакт
В отличие от sa-architect, НЕ создавай markdown-файлы в docs/. Данные Phase 1 хранятся в памяти диалога и используются в последующих фазах для создания графовых узлов.
Переход
После подтверждения пользователем -> Phase 2
Phase 2: Модульная декомпозиция
Цель: Разбить систему на 3--8 функциональных модулей (Bounded Contexts) и записать их в граф.
Принципы декомпозиции
- Single Responsibility: Каждый модуль решает одну бизнес-задачу
- High Cohesion: Сущности и UC внутри модуля тесно связаны
- Low Coupling: Минимум зависимостей между модулями
- Testable Boundary: Модуль можно описать 1--2 предложениями без "и/или"
- Balanced Size: Каждый модуль содержит 3--15 UC
- BA Alignment: Модули должны коррелировать с ProcessGroup из BA-подграфа
Построение предложения
Если в Phase 0 загружены SUGGESTS-рёбра --- используй их как стартовую точку. Иначе --- используй ProcessGroup как основу для группировки:
На основе BA-подграфа я предлагаю разбить систему на следующие модули:
1. **{Название}** (mod-{code}) --- {назначение}
- Источник: ProcessGroup "{gpr_name}"
- UC range: UC100-UC199
- Процессы: {список BP из этой группы}
- Бизнес-объекты: {список BE, связанных с процессами}
2. **{Название}** (mod-{code}) --- {назначение}
...
Вопросы:
1. Согласны с такой структурой модулей?
2. Нужно ли добавить/убрать/объединить модули?
3. Есть ли общесистемные функции (авторизация, настройки)?
- Если да, они идут в модуль mod-common (UC001-UC099)
Правила декомпозиции
- Система = 3--8 модулей
- Если модуль содержит > 15 UC --- разделить
- Если модуль содержит (m)
#### Шаг 2.4: Верификация созданных модулей
```cypher
// mcp__neo4j__read-cypher
MATCH (m:Module)
OPTIONAL MATCH (gpr:ProcessGroup)-[:SUGGESTS]->(m)
RETURN m.id AS id, m.name AS name, m.description AS description,
m.uc_range_start AS uc_start, m.uc_range_end AS uc_end,
collect(gpr.name) AS source_process_groups
ORDER BY m.uc_range_start
Покажи пользователю таблицу:
**Phase 2: Модули записаны в граф**
| Модуль | ID | UC Range | Источник (ProcessGroup) |
|--------|----|----------|-------------------------|
| {name} | {id} | UC{start}-UC{end} | {gpr_names} |
| ... | ... | ... | ... |
Всего модулей: {N}
Переход
После подтверждения модульной декомпозиции -> Phase 3
Phase 3: Context Map
Цель: Определить межмодульные зависимости и записать их в граф.
Действия
На основе BA-данных из Phase 0 и модулей из Phase 2:
- Определи направления зависимостей:
- Какой модуль от какого зависит?
- Кто владеет данными (CRUD)?
- Кто только читает данные?
- Определи типы связей:
data_read--- модуль читает справочники/сущности другого модуляoperation_call--- модуль инициирует бизнес-процесс в другом модулеevent--- модуль реагирует на изменения в другом модуле
- Определи общие сущности:
- Какие BusinessEntity из графа используются несколькими ProcessGroup?
- Определи владельца и читателей
Для анализа общих сущностей выполни:
// mcp__neo4j__read-cypher
MATCH (ws:WorkflowStep)-[:READS|PRODUCES|MODIFIES]->(be:BusinessEntity)
MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws)
MATCH (gpr:ProcessGroup)-[:CONTAINS]->(bp)
RETURN be.id AS entity_id, be.name AS entity_name,
collect(DISTINCT {gpr_id: gpr.id, gpr_name: gpr.name,
rel_type: type((ws)-[:READS|PRODUCES|MODIFIES]->(be))}) AS used_by_groups
Вопросы для пользователя
Я построил карту зависимостей между модулями:
{Текстовая таблица зависимостей}
Вопросы:
1. Правильно ли я определил направления зависимостей?
2. Есть ли зависимости, которые я пропустил?
3. Правильно ли определены владельцы общих сущностей?
Артефакт: Создание межмодульных рёбер в графе
Шаг 3.1: Создание DEPENDS_ON рёбер между модулями
Для каждой зависимости:
// mcp__neo4j__write-cypher
MATCH (m1:Module {id: $source_module_id})
MATCH (m2:Module {id: $target_module_id})
MERGE (m1)-[r:DEPENDS_ON]->(m2)
SET r.type = $dep_type,
r.description = $description
Параметры:
$source_module_id--- модуль-потребитель$target_module_id--- модуль-поставщик$dep_type---"data_read","operation_call", или"event"$description--- что передаётся (напр."Читает данные клиентов")
Шаг 3.2: Предварительное распределение BusinessEntity по модулям
На основе анализа владения --- создай предварительные CONTAINS_ENTITY-рёбра:
// mcp__neo4j__write-cypher
MATCH (m:Module {id: $module_id})
MERGE (de:DomainEntity {id: $entity_id})
SET de.name = $entity_name,
de.module = $module_id,
de.status = 'draft',
de.created = datetime()
MERGE (m)-[:CONTAINS_ENTITY]->(de)
Также создай BA-to-SA handoff-ребро:
// mcp__neo4j__write-cypher
MATCH (be:BusinessEntity {id: $ba_entity_id})
MATCH (de:DomainEntity {id: $sa_entity_id})
MERGE (be)-[:REALIZED_AS]->(de)
Шаг 3.3: Верификация Context Map
// mcp__neo4j__read-cypher
MATCH (m1:Module)-[r:DEPENDS_ON]->(m2:Module)
RETURN m1.name AS source, m2.name AS target,
r.type AS dep_type, r.description AS description
ORDER BY m1.name, m2.name
// mcp__neo4j__read-cypher
MATCH (m:Module)-[:CONTAINS_ENTITY]->(de:DomainEntity)
RETURN m.name AS module, collect({id: de.id, name: de.name}) AS entities
ORDER BY m.name
Покажи пользователю результат:
**Phase 3: Context Map записан в граф**
Зависимости:
| Источник | Приёмник | Тип | Описание |
|----------|----------|-----|----------|
| {source} | {target} | {type} | {desc} |
Распределение сущностей:
| Модуль | Сущности |
|--------|----------|
| {module} | {entity_list} |
Переход
После подтверждения Context Map -> Phase 3.5 (External Contracts)
Phase 3.5: External Contracts
Цель: Зафиксировать каждый внешний провайдер и каждый wire-протокол как отдельный артефакт-контракт, который читает граф SA, и который консумируют downstream-скилы (nacl-tl-plan, nacl-tl-sync wire-evidence gate, nacl-tl-dev-be, nacl-tl-dev-fe, nacl-tl-qa).
Why this phase exists. 13 из ~60 сигналов в постмортемах двух проектов — это сбои внешних API / wire-протоколов: kie.ai (оба проекта), TUS upload, обратный прокси https-схема, ffmpeg/ffprobe runtime, SSE frame envelope. Локально всё компилировалось, типы совпадали, но реальный wire не работал. См. docs/retrospectives/project-beta-runtime-baseline.md §§ A1–A9, B1–B7 и сводку §I "Provider/external-API contracts" и "Wire-envelope protocols". Цель этой фазы — превратить эту негативную плоскость в позитивный артефакт.
Артефакт
Один Markdown-файл на провайдер ИЛИ на протокол:
.tl/external-contracts/.md
Примеры файлов (этот скил их создаёт по результатам диалога с пользователем):
| Тип | Slug | Описание | |---|---|---| | provider | kie.md | kie.ai — LLM endpoint (Anthropic-shape), async polling lifecycle, model namespace без google/-префикса. См. baseline § A1–A3, A5, A7–A9. | | provider | deepgram.md | Deepgram (ASR) — sync provider; API key обязателен; pre-provider стадии (storage fetch, ffmpeg extract) НЕ требуют ключа (см. baseline § A4, F2). | | provider | anthropic.md | Anthropic Claude (прямой вызов) — отличный envelope от kie.ai. | | protocol | tus.md | TUS upload — Location header public-origin; Caddy respectForwardedHeaders + X-Forwarded-Proto; Fastify addContentTypeParser для application/offset+octet-stream (см. baseline § A6, B1, B2, B4). | | protocol | sse.md | Server-Sent Events — frame envelope event: \ndata: \n\n; без event:-строки браузер дефолтит на 'message' (см. baseline § B3). | | protocol | multipart-presigned.md | Прямой S3 presigned multipart upload (когда TUS заменён — см. baseline § B5). | | protocol | reverse-proxy-url-scheme.md | Общие правила https-public-URL за прокси (cross-cutting между TUS, presigned, и любыми Location-headers). | | protocol | ffmpeg-ffprobe-runtime.md | ffmpeg/ffprobe runtime — seekable stdin для MP4 demux (см. baseline § C5); ffprobe не принимает s3://-URI (§ B6). |
Шаблон с обязательными и опциональными полями: .tl/external-contracts/_template.md (создаётся в W6 как сам артефакт скила).
Required fields (для каждого файла)
| # | Поле | Описание | |---|---|---| | 1 | Identity | Имя, kind: provider|protocol, дата, ссылки на TECH-### / UC-### в графе. | | 2 | Endpoint | Полный URL включая version-path (НЕ только base host,
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ITSalt
- Source: ITSalt/NaCl
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.