惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
T
ThreatConnect
SecWiki News
SecWiki News
F
Future of Privacy Forum
AWS News Blog
AWS News Blog
C
Cisco Blogs
A
Arctic Wolf
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Scott Helme
Scott Helme
V
V2EX
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
K
Kaspersky official blog
G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Privacy International News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News | PayPal Newsroom
Schneier on Security
Schneier on Security
NISL@THU
NISL@THU
Microsoft Azure Blog
Microsoft Azure Blog
量子位
The Hacker News
The Hacker News
Stack Overflow Blog
Stack Overflow Blog
Security Latest
Security Latest
M
Microsoft Research Blog - Microsoft Research
Google Online Security Blog
Google Online Security Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
InfoQ
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
The Cloudflare Blog
Microsoft Security Blog
Microsoft Security Blog
Martin Fowler
Martin Fowler
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Troy Hunt's Blog
F
Fox-IT International blog
S
Security @ Cisco Blogs
博客园 - 司徒正美
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Comments on: Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 最新话题
GbyAI
GbyAI
Project Zero
Project Zero
腾讯CDC
T
Tailwind CSS Blog

Все публикации подряд на Хабре

Менеджер, который хакнул систему. И что AI на самом деле умножает Запись в Kubernetes: как контроллеры учились не перезаписывать друг друга Игровой движок 2.5D, короткие тренировки для ПК-пользователей –и еще 8 российских стартапов MCP в системе управления проектами: как поручить ИИ работу с корпоративными данными Бэклог болей: как hh работает с тем, что не нравится пользователям brec: контролируемая обратная совместимость протокола AI обнулил benchmark и пытался шантажировать инженера. И почему это решаемо Почему пластиковый корпус оказался в 3 раза дороже металлического Как спроектировать API, которое не придется переписывать через полгода Трекинг посетителей на fisheye-камерах: задача “со звездочкой” Красивый скриншот вашего кода. Большое обновление Я создаю проекты без единого созвона с командой Content Pipeline в MonoGame: почему я его не использую Гемблинг партнерки: Как выбрать, ТОП 5 в 2026 За пределами LLM, часть 2: якорная таблица Кэли, которая не является ни полем, ни моноидом Pixverse купить подписку: для чего нужна Пиксверс подписка, как выбрать тариф и оплатить в рублях Meshy AI нейросеть: как создавать 3D-модели из текста и изображений в Меши АИ на русском бесплатно Skywork AI: как использовать Скайворк АИ нейросеть на русском бесплатно, работать с промтами и создавать видео Технотекст 8: победа естественного интеллекта Capacitor: от веба к мобильным приложениям. Часть 4. Интегрируем локальный LLM в проект 20 лет видеокарт в цифрах: как росли FLOPS и TDP и кто вёл в дуэли NVIDIA vs AMD (+ открытый датасет на 13 500 GPU) Архитектура крипто-сканера для биржи: Open Interest, Funding Rate, EMA и MACD в реальном времени @tanstack/vue-table: почему я почти отказался от этого… WHERE превращает ваш LEFT JOIN в INNER JOIN. И никто вам об этом не скажет Гравитация не существует. Вы задали 454 вопроса о времени. Вот ответы с уравнениями Эйнштейна Конец бесплатного кремния: как Google AI Studio превратилась из рая для инженеров в симулятор смены аккаунтов Свой AI-агент из почты, systemd и LLM MemForge2: загрузочная флешка, которая за минуту говорит — какую планку памяти менять Лицензии важны. Разбор ошибок авторов и пользователей программ От RAG-прототипа к агенту в продакшн: путь по метрикам, а не по моде Serial Terminal: кастомный веб-терминал для последовательного порта на Web Serial API Китайский стартап GigaAI обещает робота-домработника за 1 млн рублей уже в 2027 году — правда или PR? Open-source VPN клиент Tunguska Роман за 6 недель без идеи на старте: миф или реальность? ИИ построит ваш план действий за 10 секунд Security Week 2622: эффективность Claude Mythos по версии Cloudflare Reactive Forms vs Signal Forms: Эволюция сложных форм в Angular TorFlash — приложение для Linux: поиск торрентов, скачивание и копирование на флешку в одно нажатие Как я решил проблему русской диктовки для ИИ Оверинжиниринг, потопивший немецкую подлодку или некоторые «баги» не чинятся десятилетиями Как ставить цели и не забывать о них: пошаговая система с примерами в таск-менеджере Как настроить observability в Spring Boot 3 HackTheBox. Прохождение Mini Pro Lab Puppet Обзор серверного ускорителя NVIDIA Tesla V100 16 Gb в корпусе от RTX 4090: Часть 3 — Запуск локальных моделей ИИ Редактирование текста нейросетью: как сделать диплом и курсовую более человечными Самодельный ARM ноутбук, реально ли? Как 100+ авторов пишут 100+ процессов в 3 версиях и не путаются. Или как мы переехали с Wiki на Git Прошла AnalystDays – хорошие выступления и нетворкинг VSCode как IDE для embedded разработки Моделирование широкополосной антенны с двойной круговой поляризацией и высокой изоляцией Ваше прошлое физически существует прямо сейчас. И вы заморожены там навсегда От списка инструментов к technical output: как security engineer’у описывать hands-on опыт в CV и на интервью I just want an agent. Часть 1. Как я научил ИИ собирать ИИ-агентов за пользователей и выиграл конкурс I just want an agent. Часть 1. Как я научил ИИ собирать ИИ-агентов за пользователей и выиграл конкурс Вайбкодинг спас меня от подрядчиков. А потом я поняла, что сама стала подрядчиком для своих агентов Святой Августин и GAN: почему борьба добра и зла — это генеративная состязательная сеть В каждом QR-коде зашита половина лишней информации. Намеренно Я открываю автомат ключом, меняю рулон бумаги и зарабатываю 180 тысяч в месяц с точки Мастер восстановления. Культура достиженства и выгорание Недельный геймдев: #279 — 24 мая, 2026 Защита от дублирования кода агентами: семантические концепции Frontend Status: свежий дайджест фронтенда и AI — 25.05.2026 Где искать IT-работу кроме HH: подборка платформ 2026 Почему простые числа собираются в спирали? OCR для Data Lakehouse: от Apache Tika к собственному решению на базе Docling Jira — Тьюринг-полная Kubernetes-аудит после Wiz и Prisma: как живут без CNAPP в 2026 «Тестируем MVP в 4 раза быстрее»: как нейросети изменили жизнь предпринимателей На каком стеке и железе работает умное наблюдение в вашем городе: обзор технологий от разработчиков видеоаналитики Как мы ускорили согласования на двух заводах в 24 раза Heartbeat-мониторинг cron-job'ов: dead-man-switch на FastAPI [Перевод] Сегодня нет джуниоров, а в 2031 году не станет и синьоров Профайлер для PostgreSQL: от идеи до работающего MVP за сутки [Перевод] Ограничения размера cookie в ASP.NET Core в продакшене: причины и способы решения Проблема «божественного» Obsidian: почему я отказался от централизованного подхода в работе Лицензии GNU GPL: как пройти проверку Минцифры и заказчика для госзакупок и КИИ Хакатон Samsung IT Academy Hack 2026: как студенты оптимизировали поиск в корпоративном мессенджере Хакатон Samsung IT Academy Hack 2026: как студенты оптимизировали поиск в корпоративном мессенджере MTProxy jumper — делаем автоматическое переключение прокси-серверов Telegram Ты уже используешь агента. Просто не заметил Книжный салон. Послевкусие и благодарности Как отлаживать мини‑приложения в MAX и почему без DevTools это боль Cбор биометрических данных. Как защищается наша биометрия на практике Как запустить учет активов без цифровой свалки: первые 90 дней CGE: визуализация кравлера и скрытых связей между поддоменами Зачем банки тратят миллиарды на науку (спойлер: не благотворительности ради) Книга: «Современный Java Concurrency. Глубокое погружение в Virtual Threads, Structured Concurrency и Scoped Values» Как использовать подписку ChatGPT и Claude в Cursor без оплаты за API токены Специализированная ИСУП или модуль в универсальной платформе: вот в чем вопрос Обход белых списков через WebRTC на стероидах (с поддержкой iOS и десктопа) Регата INFOSTART CIO CAMP: когда команда проверяется не в переговорной, а на воде Пет-проект, который не умер: система бронирования устройств как полигон для AI-разработки Не надо встраивать ИИ в каждую корпоративную систему, это архитектурная ошибка Нейросети для дизайна интерьера: Выбираем лучший ИИ для генерации концептов и планировок квартиры Что там с Ил-114-300 Что такое DAS: как и зачем продукт-менеджеры саботируют запуск новых продуктов 8% компаний измеряют критическое мышление руководителей. Что делают остальные 92% CVE, Shell и побег из контейнера: испытываем возможности PT Cloud Application Firewall Как я научил Алису петь: генерация музыки по голосовой команде Восстановление данных с помощью бесплатной утилиты Easy Disk Checker
Spec-driven development в микросервисах, часть 2: как archspec делает контекст сервисов явным
krus210 · 2026-05-26 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение11 мин

Охват и читатели0

Кейс

Вторая статья из цикла из трёх частей.

Часть 1 — где LLM теряет межсервисный контекст и почему локальных спек недостаточно.

Часть 2 — archspec как контракт вместо свободного Markdown.

Часть 3 — archspec: исследование фичи, обновление контрактов и реализация.

1. Зачем понадобился архитектурный контракт

В первой части я разбирал, почему spec-driven development начинает ошибаться, когда фича проходит через несколько микросервисов. Проблема не в том, что LLM плохо читает код или не умеет писать спеку. На уровне отдельных сервисов всё может выглядеть аккуратно: есть описание, план, реализация и тесты. Но правила, которые связывают сервисы между собой, часто не записаны в одном месте. Часть таких правил спрятана в реализации, часть известна только команде, а часть всплывает уже на ревью. Обычный Markdown не решает эту проблему: его легко написать неполным, сложно проверить автоматически и почти невозможно ревьюить как структурный контракт.

Отсюда родилась идея: нужен машиночитаемый контракт на каждый сервис, который фиксирует межсервисные правила, проверяется на коммите и даёт LLM структурный контекст вместо набора Markdown-файлов. Для этого я собрал open source плагин для Claude Code — archspec.

В этой части я покажу, как работает /archspec:init на одном сервисе из демо-проекта freelance-marketplace, разберу сгенерированные артефакты и объясню, как archspec поддерживает их в актуальном состоянии. Напомню, это Go-проект с 12 микросервисами для поиска фрилансеров. Вот схема сервисов, которую я использую на протяжении всего цикла:

Схема сервисов

2. Как инициализируется архитектурный контракт

В качестве примера я беру task-service. В демо-проекте он отвечает за задачи: хранит их состояние и публикует task.created, после чего подбором кандидатов занимается matching-service. У сервиса есть важное ограничение: если операция меняет задачу и должна опубликовать событие, изменение состояния и событие должны записываться вместе через Outbox. В текущем стенде сервис специально упрощён: хранилище in-memory, а ключи идемпотентности пока не сохраняются.

2.1. Запуск /archspec:init

Скил /archspec:init добавляет в сервис четыре вещи: спеку, то есть машиночитаемый YAML-контракт архитектуры (docs/SERVICE_MAP.yaml); страницу архитектуры для разработчиков (docs/ARCHITECTURE.md); три диаграммы в docs/diagrams/; а также pre-commit хуки, которые запускаются перед коммитом и проверяют, что сгенерированные файлы не разъехались со спекой. Диаграммы нужны для разных уровней детализации: context показывает внешние связи сервиса, container — каналы взаимодействия и хранилища, а sequence — путь конкретного запроса. Главное правило здесь простое: руками правится только спека, а всё остальное генерируется из неё. Ниже ещё покажу, как это поддерживается хуками.

2.2. Проектная архитектура: подсказка, а не источник истины

Скил может взять проектный architecture.md как подсказку для общей схемы сервисов. В демо-проекте такого файла нет, поэтому я отвечаю skip; факты о самом сервисе скил всё равно проверит по репозиторию.

2.3. Базовые данные о сервисе

Дальше скил просит заполнить базовые данные: имя сервиса, команду-владельца, домен (bounded context — обособленная часть предметной области со своей моделью) и URL репозитория. Имя сервиса по умолчанию берётся из имени директории, потому что скил видит, где он запущен.

2.4. Что сервис делает и что гарантирует

На этом шаге важно коротко зафиксировать, за что отвечает сервис и какие правила он обязан соблюдать. Для task-service это хранение задач, публикация task.created через Outbox и контроль переходов статусов. Отдельно я записываю гарантии: запись должна идти через Outbox, а id задачи не должен меняться. Эти ответы потом попадут и в YAML-спеку, и в страницу архитектуры.

2.5. Что можно достать из кода автоматически

После ручных ответов скил читает репозиторий и собирает факты, которые не хочется переписывать вручную: какие RPC и HTTP-ручки есть у сервиса, какие события он публикует, какие хранилища использует и где находится основная модель записи. Это важно не только для удобства. Если контракт собирается из кода, меньше шансов случайно описать ручку, которой уже нет, или забыть событие, которое сервис реально отправляет.

2.6. Где нужна идемпотентность и какие SLA известны

Дальше скил проходит по найденным ручкам и уточняет то, что в коде часто не видно напрямую. Для команд вроде CreateTask важно понять, нужна ли идемпотентность, откуда берётся ключ и где он хранится. В моём примере ключ требуется, но хранилища для него ещё нет, поэтому я выбираю not-implemented. SLA тоже фиксируется явно: если метрика уже есть, её можно записать сразу; если нет, остаётся not-measured.

2.7. Хранилища, события и Outbox

На этом шаге в контракт попадают хранилища и события. Для task-service это in-memory:task-store и событие task.created версии 1. Здесь же становится видно, может ли сервис использовать Outbox: для этого у него должны быть и состояние, которое меняется, и событие, которое нужно опубликовать вместе с этим изменением.

2.8. Какие сервисы зависят от task-service

Контракту важно знать не только зависимости самого сервиса, но и тех, кто его вызывает. Поэтому я указываю корень монорепо, а скил ищет потребителей task-service. В этом примере он находит api-gateway. Это полезно на ревью: если меняется контракт task-service, сразу видно, какие сервисы потенциально затронуты.

2.9. Главный агрегат и путь записи

Скил также просит подтвердить главный агрегат и путь записи. В коде он видит техническое имя MemoryTask, но в контракте лучше использовать бизнес-имя task: так спеку проще читать не только автору кода. Паттерн outbox выбирается не по умолчанию, а по роли сервиса. Он нужен там, где сервис сам меняет своё состояние и вместе с этим должен опубликовать событие. У task-service как раз такой случай: он хранит задачи и публикует task.created. А stateless-шлюз вроде api-gateway состояние не хранит, поэтому ему нечего записывать через Outbox.

2.10. Правила между сервисами

Последний шаг — записать правила, которые относятся не к одному сервису, а к его взаимодействию с другими сервисами. Например, кто должен обработать task.created, как защищаться от дублей и какие гарантии ожидают потребители события. Это как раз тот слой, который плохо виден в локальном CLAUDE.md: сервис может быть описан правильно, но его договорённости с другими сервисами всё равно останутся неявными.

2.11. Что получилось после init

Итог сессии: 3 ручки, одно публикуемое событие, один потребитель, in-memory хранилище, outbox и агрегат task. В контракте также остаются явно отмеченные незакрытые места. Например, для CreateTask идемпотентность нужна, но хранилища ключей в сервисе пока нет (IDEMP-001). У события task.created пока нет отдельной схемы (DOC-002). Поэтому на ревью видно не только то, что уже есть в сервисе, но и то, что ещё нужно доделать. Весь init занял около трёх минут на сервис.

3. Что сгенерировал archspec

3.1. YAML-контракт сервиса

Спека — это машиночитаемый контракт сервиса в одном YAML-файле. В ней лежит именно то, что терялось в первой части: зона ответственности, инварианты, ручки с признаком идемпотентности, путь записи (тот самый Outbox), события и главные агрегаты. Файл получается небольшим, обычно на пару сотен строк, поэтому LLM быстро читает его целиком. У task-service спека выглядит так; показываю только одну ручку, чтобы не раздувать пример:

service:
  responsibilities:
    - "create and persist freelance tasks"
    - "publish task.created events via outbox"
  invariants:
    - "every write goes through the outbox"
    - "task IDs are unique and immutable"
api:
  endpoints:
    - name: CreateTask
      protocol: gRPC
      idempotency:
        required: true
        key_source: "metadata: x-idempotency-key"
        storage: "not-implemented"
      sla:
        p99_latency: "500ms"
        availability: "99.9%"
events:
  published:
    - topic: task.created
      version: 1
consistency:
  write_path:
    pattern: outbox
concurrency:
  aggregates:
    - name: task
      write_strategy: optimistic

storage: not-implemented — это не баг генерации, а явная отметка: ключ идемпотентности на ручке требуется, но хранилища ключей в коде ещё нет. Полный файл лежит здесь: SERVICE_MAP.yaml.

3.2. Страница архитектуры для разработчиков

Страница архитектуры содержит те же данные, что и спека, но в форме обычного Markdown: таблицу ручек с протоколами и SLA, списки зависимостей, событий, хранилищ и ссылки на диаграммы. По формату это обычный README, который GitHub показывает в PR без дополнительных инструментов.

Внутри файла стоят маркеры <!-- archspec:managed-region:start --> и <!-- archspec:managed-region:end -->. Всё, что находится между ними, при каждой регенерации перезаписывается из спеки. Всё за пределами этого блока можно редактировать вручную: добавить историю сервиса, runbook или заметки по эксплуатации. Pre-commit проверяет только сгенерированный блок и не трогает эти разделы.

Кусок таблицы ручек у task-service:

Endpoint

Protocol

Idempotent

SLA p99

CreateTask

gRPC

yes

500ms

GetTask

gRPC

no

not-measured

ListTasks

gRPC

no

100ms

Полный файл лежит здесь: ARCHITECTURE.md.

3.3. Диаграммы, которые обновляются из спеки

Диаграммы хранятся в docs/diagrams/ отдельными файлами в Mermaid-формате. GitHub и Habr рендерят Mermaid прямо из Markdown, без дополнительных инструментов.

  • Context (C1). Общий вид: кто вызывает сервис снаружи, какие у него хранилища и какие события он публикует. Внутренних деталей здесь нет.

  • Container (C2). Тот же сервис, но связи помечены типом: sync — downstream gRPC, async — события, storage — хранилище, publish/consume — топики. По этой диаграмме видно, через какие каналы ходят данные.

  • Sequence. По одному обращению на каждую ручку, с чтением заголовка идемпотентности и записью в Outbox. Этого достаточно, чтобы понять основной путь запроса.

container.mmd для task-service:

Фрагмент sequence.mmd для CreateTask:

В PR ревьюер видит структурный диф архитектуры рядом с дифом кода. На больших монорепо этого часто не хватает: код меняется, а схема взаимодействия сервисов не попадает в ревью. Полные диаграммы лежат в docs/diagrams/.

3.4. Блок для Claude Code

Ещё один артефакт появляется в CLAUDE.md сервиса. Это небольшой сгенерированный блок, который объясняет Claude Code, как работать с архитектурным контрактом: сначала читать docs/SERVICE_MAP.yaml, перед нетривиальной задачей запускать /archspec:investigate, после изменения спеки запускать /archspec:sync, а перед merge проверять результат через /archspec:validate.

Смысл простой: CLAUDE.md остаётся входной точкой для агента, но теперь он не заменяет архитектурный контракт. Он направляет Claude Code к спеке и напоминает, что диаграммы и сгенерированную часть ARCHITECTURE.md нельзя править вручную.

4. Какие проблемы решает контракт

4.1. Документация не должна расходиться с контрактом

Хуки блокируют ручную правку сгенерированной страницы и диаграмм, потому что без такой защиты они быстро разойдутся со спекой. Кто-то поправит таблицу ручек в ARCHITECTURE.md, забудет про YAML, и в PR появятся изменения, которых на самом деле нет в контракте сервиса. В итоге документация начнёт описывать не тот сервис, который лежит в репозитории.

4.2. В контракте должны быть видны незакрытые места

Раньше в примере с CreateTask было видно: идемпотентность нужна, но хранилища ключей пока нет. В обычной документации это место легко сгладить или случайно описать так, будто всё уже реализовано. В контракте лучше оставить явную отметку not-implemented: так ревьюер сразу видит, что правило уже зафиксировано, но код ещё не закрывает его полностью.

Такие отметки нужны не только для идемпотентности. not-documented показывает, что код есть, но схемы в proto или OpenAPI ещё нет. not-measured означает, что SLA указан как требование, но метрика пока не снимается. Это не финальное состояние, а понятный список того, что ещё нужно доделать.

4.3. Outbox появляется только там, где он возможен

Паттерн outbox прописывается только тогда, когда у сервиса есть и публикуемые события, и долговременное хранилище. Например, api-gateway только принимает запросы и передаёт их дальше, но сам не хранит состояние задачи. Значит, ему не нужен Outbox: ему нечего записывать вместе с событием. Это закрывает один из частых классов ошибок из первой части: в спеке события выглядят «как бы атомарными» с записью, хотя в реальном коде этой атомарности нет.

4.4. Генерация должна быть предсказуемой

Один и тот же код должен давать один и тот же результат в спеке. Иначе разработчик запускает синхронизацию, ничего по сути не меняет, а в Git появляется лишний диф. После нескольких таких случаев хукам перестают доверять: они начинают выглядеть как шум, а не как проверка архитектуры. Поэтому генерация должна быть предсказуемой, чтобы в PR попадали только реальные изменения.

4.5. Потребителей сервиса лучше искать скриптом, а не просить LLM

Поиск потребителей сервиса лучше делать автоматически. Это механическая задача: нужно пройтись по монорепо и понять, кто вызывает task-service. LLM может помочь объяснить результат, но сам список потребителей должен собираться скриптом, чтобы не пропустить связь между сервисами. Перед применением изменений archspec показывает, что именно будет добавлено в спеку, и даёт выбор: применить всё, отредактировать вручную или пропустить.

5. Как контракт остаётся актуальным

5.1. Проверка запускается перед коммитом

В конце init archspec добавляет шаг перед git commit. Он не заменяет существующие pre-commit хуки проекта, а выполняется вместе с ними. Если спека, страница архитектуры или диаграммы расходятся между собой, разработчик увидит это до коммита.

5.2. Что проверяется перед коммитом

Перед коммитом archspec сверяет спеку, страницу архитектуры, диаграммы и найденные связи между сервисами. Проверка ловит несколько типичных проблем:

  • ручную правку сгенерированного блока в ARCHITECTURE.md или диаграммах;

  • литерал TODO в обязательных полях спеки;

  • паттерн записи outbox без долговременного хранилища;

  • сервис вызывает другой, но не записан как его потребитель;

  • идемпотентность задекларирована, а хранилища для ключей в спеке нет.

По умолчанию это предупреждения (WARN). Чтобы сделать их блокирующими (BLOCK), в спеке включается строгий режим. Обычно его включают не сразу: на старых сервисах сначала может появиться много предупреждений, и команде удобнее разобрать их постепенно, а не получить заблокированный коммит в первый же день.

5.3. Как выглядит обычный цикл обновления

Обычный цикл такой: разработчик меняет контракт сервиса, а затем запускает /archspec:sync. Из обновлённой спеки заново собираются страница архитектуры и диаграммы, поэтому их не нужно править вручную. В PR попадает один связанный набор изменений: код, контракт и сгенерированная документация. Ревьюер видит не только новый метод или событие, но и то, как из-за него изменилась схема сервиса.

5.4. Как проверить связи между сервисами

После init отдельных сервисов полезно посмотреть на проект целиком. Для этого есть /archspec:check-architecture: он читает все спеки сразу и ищет несостыковки между ними. Например, один сервис вызывает другой, но это не отражено в контракте; событие публикуется, но у него нет потребителя; в спеке указана инфраструктура, которой нет в зависимостях сервиса. Проверка ничего не правит сама, а только показывает список проблем, чтобы команда могла разобрать их отдельно.

6. Что дальше

После /archspec:init у сервиса появляется YAML-контракт, страница архитектуры и диаграммы. Эти файлы лежат рядом с кодом и обновляются из одной спеки, поэтому их уже можно использовать как контекст для LLM до начала реализации.

В третьей части я вернусь к задаче Smart Task Reassignment из первой статьи: если выбранный фрилансер отказался от оффера, система должна автоматически выбрать следующего кандидата и отправить новый оффер. На этой задаче проверю следующий шаг: что изменится, если дать LLM не набор локальных Markdown-файлов, а обновлённые архитектурные контракты сервисов. Посмотрю, какие из шести межсервисных ошибок получится поймать уже на этапе планирования.

Оба репозитория открыты:

Если найдёте баг или неудобный сценарий, создайте issue в репозитории archspec.

Часть 3 — на подходе.