Pull to refresh
-2
Александр Рогов@Ra2007

Full-Stack JS Architect

0,1
Rating
Send message

Справедливо поймали. Я немного смешал два разных слоя. Инварианты это “что нельзя менять”, а зачем существует это уже контекст для агента чтобы он понял почему эти инварианты вообще есть. В практике мы писали и то и другое вместе, потому что инвариант без объяснения зачем он нужен агент обходит первым же рефакторингом, находит другой путь который формально ничего не ломает. Но вы правы что это разные вещи и я их смешал в одну фразу.

Покопался. Интересно что воркфлоу прямо командами прописан, /discovery → /plan → /implement, и под каждый этап своя роль. У нас в итоге тоже пришли к разделению на agents/commands/standards, но без явного переключения между этапами, агент сам решал что делать дальше и это иногда вылезало в странных местах. Спасибо за пример, буду смотреть что внутри commands.

Мы до логирования confidence дошли примерно через месяц боли. Просто смотрели, модель ошиблась, и всё, непонятно было даже в какую сторону копать. Потом начали писать candidate scores и сразу стало видно что это не ошибка, а реально почти одинаковые веса у двух tools. Цикл да, у нас так же несколько кейсов буквально выкристаллизовались в explicit parsing, сначала в логах видишь что каждый раз одно и то же, потом просто хардкодишь. Какую 0.5b используете на е2е, Qwen?

Про eslint-plugin-fsd, вы правы, написал неточно. Официальный инструмент сейчас это @feature-sliced/steiger, раньше был eslint-plugin-import-fsd. eslint-plugin-boundaries тоже работает, мы примерно так и конфигурировали, прописывали разрешённые импорты между слоями вручную. Про ревью полностью согласен: агент не скроллит и держит весь граф в контексте одновременно, человек не может. Это один из неожиданных плюсов FSD+агент именно для командной работы, а не только для чистоты кода.

Столкнулись с FSD в контексте Claude Code и эффект неожиданный. Явная слоистая структура оказалась плюсом для агентов: когда написано что виджет не может импортировать из другого виджета, это ограничение работает и как guardrail для AI. Агент знает куда можно положить код а куда нельзя, не потому что умный, а потому что в CLAUDE.md дублируем ключевые правила FSD. Проблема которую вы описываете с кросс-импортами стала у нас первым местом где агент нарушает архитектуру: видит удобный импорт, делает его, тесты зелёные, а FSD сломан. Детектим только на code review. Пробовали eslint-plugin-fsd как защитный слой? У нас немного помогает, но не на 100%.

MCP в браузере, это закономерный следующий шаг. Использую MCP-серверы в Claude Code уже полгода, и разница между «агент скрапит страницу» и «агент вызывает явный tool» точно такая же по ощущениям. Только у нас это между агентом и кодовой базой, у тебя между агентом и пользовательским интерфейсом, принцип один и тот же. Интересно про security-модель: JS на странице регистрирует tools в браузере, браузер отдаёт их агенту. Кто верифицирует что tool делает то что написано в description? Вижу вектор где злоумышленник регистрирует tool с misleading description и агент делает что-то нежелательное по незнанию. Или это в спецификации уже адресовано?

Паттерн deterministic-first с LLM как fallback, нашли то же самое с Claude Code, только на кодовой базе а не на роутере. Сначала пытались положиться на модель во всём, она раз за разом принимала «творческие» решения там где нужна строгость. Выход тот же: явные правила вперёд, LLM только туда куда правила не дотягиваются. У нас это CLAUDE.md с explicit запретами на уровне каждого модуля, ты реализовал то же самое в виде каскада slash-команды → regex → rule-based → semantic. Принцип идентичный. Вопрос: когда LLM ошибается и выбирает «почти правильный» tool, как это логируешь? Интересно есть ли паттерн в ошибках, который потом можно перенести в deterministic слой.

Интересно что фундамент один и тот же, только пришли к нему с разных сторон. У меня не фриланс а продакшн монорепо на 200К+ строк TypeScript, и первой сломавшейся вещью тоже стал контекст. Модель теряет решения не потому что тупит, а потому что нет явного места где написано «вот что нельзя трогать и почему». Spec-driven подход это и решает, у нас оформилось в CLAUDE.md на уровне каждого модуля с архитектурными инвариантами. Особенно согласен про первый тезис про архитектурное мышление, именно так и ощущается смещение фокуса. Руки освобождаются, голова переключается на уровень выше. Любопытно про Skills как стандарт, использую их для ленивой загрузки инструкций под конкретный тип задачи. Как разделяешь Skills и CLAUDE.md в своей методике?

Пришёл к тому же самостоятельно, только с другого конца. Начал с того, что попросил Claude Code сделать обложку для статьи, сначала пробовал через markdown с ASCII, выглядело ужасно. Переключился на HTML/CSS плюс SVG, Claude за один заход сделал то, на что у меня ушло бы полдня в Figma. Теперь весь визуал через HTML, схемы архитектуры, DDD-контексты, презентации для команды. Особенно хорошо зашли SVG-диаграммы когда надо показать bounded contexts и их взаимодействие, Claude рисует их точнее чем любой ASCII. Единственный минус который нашёл, это diff в git. Markdown меняется на пару строк, HTML превращает правку заголовка в портянку. Для личных артефактов не критично, для командных спеков немного неудобно.

Полгода в продакшене с Claude Code, и главная боль именно здесь. Агент понимает что написано, но зачем принято конкретное решение, не видит совсем. Тесты зелёные, код компилируется, а архитектурное намерение растворилось. Нас выручил CLAUDE.md на уровне каждого модуля, туда писали не документацию, а буквально запреты: вот это нельзя вынести наружу, вот это нельзя обобщить, потому что тут бизнес-инвариант. По TDD согласен, это реально единственная честная обратная связь для агента, красный или зелёный, без интерпретации. Ещё от себя: DDD с чёткими bounded contexts работает лучше чем ожидал, агент редко лезет за границы контекста если они явно прописаны.

Тесты отвечают на вопрос «что должно получиться», а CLAUDE.md на уровне модуля отвечает на «зачем это существует и что категорически нельзя делать». Разница принципиальная. Тест проверит, что calculateTax() возвращает правильное число. Но он не скажет агенту: «эта функция обязана учитывать российское налоговое законодательство, не рефакторь её в generic-утилиту и не выноси логику округления наружу». Именно такие архитектурные инварианты мы писали в CLAUDE.md. Плюс тесты агент читает как данность, а CLAUDE.md он получает как контекст до генерации. Это меняет способ рассуждения, а не только верификацию результата.

Интересный кейс. У нас похожий опыт, только JS в strict TypeScript, примерно 200K строк. Главный инсайт: проблема больших миграций не в конвертере, а в контексте. Агент технически правильно переписывает код, но теряет смысл, «зачем эта функция вообще существует».
Решали через батчи по модулям с явным CLAUDE.md на уровне каждого модуля, туда писали инварианты и бизнес-логику, которую нельзя сломать. Это дало AI нужный контекст.
Как у вас было организовано понимание «намерения» кода, а не только его структуры? Промпты были под конкретные паттерны или более генерализованные?

Пробовал похожий подход на монорепо ~150K строк TypeScript. Проблема grep-подхода именно такая как описано: у нас везде IdentityVerifier, но Claude Code раз за разом grep-ает auth и читает не те файлы. Семантический поиск через эмбеддинги правильное направление. Из нюансов: Docker-зависимость делает SocratiCode чуть тяжеловатым для onboarding новых разработчиков. Кто-нибудь пробовал на монорепо с несколькими независимыми сервисами? Интересно, как он справляется с изоляцией контекста между сервисами чтобы агент при запросе к auth-сервису не тянул сущности из payment-сервиса

Information

Rating
4,534-th
Location
Россия
Date of birth
Registered
Activity

Specialization

Full-Stack JS Architect
Старший
JavaScript
React
TypeScript
Node.js
React Native
MobX
Next.js
Redux
GraphQL
WebSockets