<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mikhail Shogin (Mike Shogin) - Systems Architect on Mikhail Shogin</title><link>https://mshogin.com/</link><description>Recent content in Mikhail Shogin (Mike Shogin) - Systems Architect on Mikhail Shogin</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Mikhail Shogin</copyright><lastBuildDate>Wed, 29 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mshogin.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Спека как живой контракт: SPDD, archlint и двусторонний sync</title><link>https://mshogin.com/notes/spdd-and-archlint-living-spec/</link><pubDate>Wed, 29 Apr 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/spdd-and-archlint-living-spec/</guid><description>&lt;h2 id="симптом"&gt;Симптом
&lt;/h2&gt;&lt;p&gt;LLM в кодовой базе ускоряет одного разработчика. Команда от этого не ускоряется — наоборот, на ревью обрушивается поток сгенерированного кода, который никто не успевает понять. Спека, написанная на старте задачи, через неделю уже не описывает то, что в master. Кто-то правит код, кто-то правит .md, через месяц расхождение замолчано.&lt;/p&gt;
&lt;p&gt;Это не про дисциплину команды. Это про архитектуру процесса, в которой &amp;ldquo;спека&amp;rdquo; и &amp;ldquo;код&amp;rdquo; не имеют формальной связи.&lt;/p&gt;
&lt;h2 id="диагноз-от-thoughtworks"&gt;Диагноз от Thoughtworks
&lt;/h2&gt;&lt;p&gt;28 апреля 2026 на сайте Мартина Фаулера вышла статья &lt;a class="link" href="https://martinfowler.com/articles/structured-prompt-driven/" target="_blank" rel="noopener"
&gt;Structured Prompt-Driven Development&lt;/a&gt; от Wei Zhang и Jessie Xia. Они формулируют проблему точнее, чем я: &amp;ldquo;Local speed improves. But that doesn&amp;rsquo;t automatically translate into system-level throughput.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Их предложение в трёх пунктах:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Промпт — это first-class артефакт.&lt;/strong&gt; Версионируется, ревьюется, переиспользуется как код. Не реплика в чате.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;REASONS Canvas&lt;/strong&gt; — 7-частная структура промпта: Requirements, Entities, Approach, Structure, Operations, Norms, Safeguards. Первые четыре — абстракция, пятый — исполнение, последние два — governance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Замкнутая петля между промптом и кодом&lt;/strong&gt; с правилом, что обновлять первым:
&lt;ul&gt;
&lt;li&gt;изменение поведения -&amp;gt; сначала промпт, потом код&lt;/li&gt;
&lt;li&gt;рефакторинг -&amp;gt; сначала код, потом sync обратно в промпт&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Третий пункт — главное. Он превращает вечный спор &amp;ldquo;что source of truth&amp;rdquo; в процедуру.&lt;/p&gt;
&lt;h2 id="где-это-совпало-с-моей-практикой"&gt;Где это совпало с моей практикой
&lt;/h2&gt;&lt;p&gt;У меня уже был свой spec-driven workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/my/archlint/templates/specifications/spec-template.md&lt;/code&gt; — шаблон спеки с разделами Architecture, Requirements, Acceptance Criteria, Implementation Steps. Размерные градации XS/S/M/L/XL.&lt;/li&gt;
&lt;li&gt;Правило в &lt;code&gt;~/.claude/rules/spec-workflow.md&lt;/code&gt;: &amp;ldquo;задача &amp;gt;30 минут или &amp;gt;3 шагов — обязательно спека до старта&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Команда &lt;code&gt;/ms-add-spec&lt;/code&gt; в Claude Code, которая генерирует спеку под задачу.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;archlint&lt;/code&gt; — статический анализатор, который валидирует архитектурные правила (200+) на графе из AST.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;REASONS Canvas почти один в один ложится на мой шаблон:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;REASONS&lt;/th&gt;
&lt;th&gt;Мой шаблон&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;R Requirements&lt;/td&gt;
&lt;td&gt;## Requirements (FR1, FR2, &amp;hellip;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E Entities&lt;/td&gt;
&lt;td&gt;## Architecture / Data Model (UML Class)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Approach&lt;/td&gt;
&lt;td&gt;## Overview / Solution Summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S Structure&lt;/td&gt;
&lt;td&gt;## Architecture / Component Overview (C4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O Operations&lt;/td&gt;
&lt;td&gt;## Implementation Steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N Norms&lt;/td&gt;
&lt;td&gt;(не было отдельного раздела)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S Safeguards&lt;/td&gt;
&lt;td&gt;(не было отдельного раздела)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Совпадение на 70-80%. Архитектурный governance у меня вообще сильнее — &lt;code&gt;archlint&lt;/code&gt; проверяет автоматически то, что в SPDD держится на ревьюере-человеке.&lt;/p&gt;
&lt;h2 id="где-spdd-добавил-то-чего-не-было"&gt;Где SPDD добавил то, чего не было
&lt;/h2&gt;&lt;p&gt;Два пункта, которые у меня отсутствовали или были сформулированы неверно.&lt;/p&gt;
&lt;h3 id="1-спека-неизменна-в-процессе"&gt;1. Спека &amp;ldquo;неизменна в процессе&amp;rdquo;
&lt;/h3&gt;&lt;p&gt;В моём &lt;code&gt;spec-workflow.md&lt;/code&gt; буквально стояла формулировка:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Спека = ЧТО делать (неизменна в процессе)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это противоположно идее живого артефакта. Спека написана, согласована, перенесена в &lt;code&gt;inprogress/&lt;/code&gt; — и потом никем не трогается, пока задача не закроется. На практике это значит, что любая правка реализации, отличающаяся от плана, проваливается между спекой и кодом.&lt;/p&gt;
&lt;h3 id="2-norms-и-safeguards-неявные"&gt;2. Norms и Safeguards неявные
&lt;/h3&gt;&lt;p&gt;Стандарты команды (как именно мы оборачиваем ошибки, какой logger, какие naming-конвенции) у меня живут в куче .md файлов: &lt;code&gt;~/.claude/rules/architecture.md&lt;/code&gt;, проектные CLAUDE.md, в чате. На уровне отдельной спеки их явно никто не выносит. Авторы SPDD выделяют:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Norms&lt;/strong&gt; — стандарты как принято писать. Часть автоматизирована (golangci-lint, archlint), часть нет.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safeguards&lt;/strong&gt; — неприкосновенные инварианты. Нарушение — стоп, не warning. Обратная совместимость, perf budgets, security boundaries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Когда они в одной странице со спекой, тихий рефактор поперёк стандарта становится заметным на ревью.&lt;/p&gt;
&lt;h2 id="что-я-в-итоге-сделал"&gt;Что я в итоге сделал
&lt;/h2&gt;&lt;p&gt;Два патча, оба сегодня.&lt;/p&gt;
&lt;h3 id="патч-1-clauderulesspec-workflowmd"&gt;Патч 1: &lt;code&gt;~/.claude/rules/spec-workflow.md&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;Удалил &amp;ldquo;Спека неизменна&amp;rdquo;. Заменил на &amp;ldquo;Спека — живой контракт, синхронизирован с кодом всегда&amp;rdquo;. Добавил раздел &amp;ldquo;Двусторонняя синхронизация&amp;rdquo; с явным правилом prompt-first vs code-first:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Изменение поведения (publicly-exposed контракт, бизнес-логика, валидация)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; сначала спека, потом код
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Рефакторинг (поведение не меняется)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-&amp;gt; сначала код, потом sync обратно в спеку
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;И отдельный раздел &amp;ldquo;Norms и Safeguards: governance внутри спеки&amp;rdquo; с примерами и привязкой к archlint/golangci-lint.&lt;/p&gt;
&lt;h3 id="патч-2-myarchlinttemplatesspecificationsspec-templatemd"&gt;Патч 2: &lt;code&gt;~/my/archlint/templates/specifications/spec-template.md&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;Добавил две секции после Acceptance Criteria:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Norms
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; N1: error wrapping через fmt.Errorf(&amp;#34;%w&amp;#34;) или errtrace.Wrap
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; N2: логирование через slog с контекстом
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; N3: naming - DB snake_case, JSON camelCase
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Автоматизировано:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; golangci-lint passes (errcheck, errorlint, sloglint)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; archlint passes (layered, fan-out, ISP)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Safeguards
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; S1: обратная совместимость публичного API в рамках minor релиза
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; S2: p99 latency endpoint X не растёт более чем на 10%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; S3: нет утечки PII в логи и метрики
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Проверка:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Smoke test на обратную совместимость
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Бенчмарк до/после
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Аудит логов на чувствительные поля
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Размерные градации те же: для XS Safeguards обычно не нужны, для M/L/XL — обязательны.&lt;/p&gt;
&lt;h2 id="что-я-не-взял"&gt;Что я НЕ взял
&lt;/h2&gt;&lt;p&gt;Не взял CLI &lt;code&gt;openspdd&lt;/code&gt; и команду &lt;code&gt;/spdd-prompt-update&lt;/code&gt;. Слишком много церемонии для одиночной работы и для команды без отдельного workflow-инженера. У меня та же дисциплина держится на:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/ms-add-spec&lt;/code&gt; — создать спеку&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/ms-checkpoint&lt;/code&gt; — зафиксировать прогресс на длинной задаче&lt;/li&gt;
&lt;li&gt;&lt;code&gt;archlint&lt;/code&gt; — валидация Norms+Safeguards автоматически где можно&lt;/li&gt;
&lt;li&gt;Code review через GitLab — двусторонний sync проверяется на ревью&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Не взял правило &amp;ldquo;никогда не редактировать промпт руками&amp;rdquo;. У них это compensation за CLI-managed lifecycle. У меня его нет, и руками править .md спеку — нормальная операция.&lt;/p&gt;
&lt;p&gt;Не взял заявление про &amp;ldquo;~99% intent alignment&amp;rdquo;. Это маркетинг, кейс N=1.&lt;/p&gt;
&lt;h2 id="двойная-оптика"&gt;Двойная оптика
&lt;/h2&gt;&lt;p&gt;Технический слой статьи: дисциплина для AI-кодинга в команде.&lt;/p&gt;
&lt;p&gt;Архитектура мышления за этим: проблема, которую решают авторы — не &amp;ldquo;AI пишет неправильный код&amp;rdquo;, а &amp;ldquo;bandwidth ревьюера не растёт со скоростью генератора&amp;rdquo;. Когда LLM выдаёт результат быстрее, чем человек успевает его понять, узкое место — когнитивная пропускная способность того, кто принимает изменения. SPDD сжимает то, на чём держится ревью, до одного артефакта (Canvas), чтобы он влезал в bandwidth.&lt;/p&gt;
&lt;p&gt;Это та же задача, про которую я говорил на Стачке — контроль сложности через граф. Только на уровне процесса, а не статического анализа.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;archlint&lt;/code&gt; = governance внутри кода (граф, правила, инварианты).
SPDD/спека = governance над изменениями (контракт между намерением и реализацией).&lt;/p&gt;
&lt;p&gt;Эти две вещи комплементарны, не конкурируют. Если у тебя есть один без другого, ты получаешь либо красивые архитектурные правила без контракта на изменения, либо пухлые спеки без автоматической проверки.&lt;/p&gt;
&lt;p&gt;Когда есть оба — каждый коммит проходит и через &amp;ldquo;не сломал ли архитектуру&amp;rdquo; (archlint), и через &amp;ldquo;соответствует ли намерению&amp;rdquo; (спека). На ревьюера падает только то, что обе автоматизации пропустили.&lt;/p&gt;
&lt;h2 id="ссылки"&gt;Ссылки
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Оригинал статьи: &lt;a class="link" href="https://martinfowler.com/articles/structured-prompt-driven/" target="_blank" rel="noopener"
&gt;Structured Prompt-Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openspdd&lt;/code&gt; (Thoughtworks-affiliated CLI): &lt;a class="link" href="https://github.com/gszhangwei/open-spdd" target="_blank" rel="noopener"
&gt;https://github.com/gszhangwei/open-spdd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;archlint: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;https://github.com/mshogin/archlint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Совет умирает. Вопрос остаётся</title><link>https://mshogin.com/notes/compass-in-ai-era/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/compass-in-ai-era/</guid><description>&lt;p&gt;Я 20 лет копил техническую экспертизу. За последние полтора года значительная её часть стала доступна любому, у кого есть подписка на нейросеть за 20 долларов.&lt;/p&gt;
&lt;p&gt;Этот вопрос всплывает у меня периодически: насколько ценен мой опыт сегодня?&lt;/p&gt;
&lt;h2 id="ai-не-плохо-отвечает-ai-поддерживает"&gt;AI не &amp;ldquo;плохо отвечает&amp;rdquo;. AI поддерживает
&lt;/h2&gt;&lt;p&gt;Да, AI знает глубже, шире, точнее меня. И всё же есть особенность: AI поддерживает. Какое бы направление оператор ни выбрал - AI развивает именно выбранное.&lt;/p&gt;
&lt;p&gt;Это даже не плохо. Молодой инженер с GPT движется в проблеме быстрее, чем я когда-то лопатил Stack Overflow и форумы по выходным.&lt;/p&gt;
&lt;p&gt;Что мне даёт опыт - в какой-то момент сказать &amp;ldquo;стоп&amp;rdquo;. Развернуть. Потому что на эти грабли я уже наступал, и помню, как они выглядят.&lt;/p&gt;
&lt;p&gt;Но смотрите дальше. Говорю AI: &amp;ldquo;Стоп. В моём прошлом проекте этот путь не сработал. Давай развернёмся&amp;rdquo;. Он отвечает: &amp;ldquo;Точно, отличная идея&amp;rdquo;. И теперь поддерживает развёрнутый вариант.&lt;/p&gt;
&lt;p&gt;AI равно поддерживает любую мою сторону. И прежнюю, и развёрнутую.&lt;/p&gt;
&lt;p&gt;И вот это - мой настоящий вопрос. На что опираться, если AI быстрее меня в ответах и подыгрывает любому моему выбору?&lt;/p&gt;
&lt;h2 id="поворот-которого-я-не-ожидал"&gt;Поворот, которого я не ожидал
&lt;/h2&gt;&lt;p&gt;Ответ пришёл с неожиданной стороны: в этом году я учусь на коуча. Скоро экзамен ICF Level 1.&lt;/p&gt;
&lt;p&gt;И эта учёба меня прижала.&lt;/p&gt;
&lt;p&gt;Я всю жизнь работал в том же режиме, что AI. Только медленнее.&lt;/p&gt;
&lt;p&gt;Подходит коллега с проблемой - страх, сомнение, выбор. Я уже знаю, что ему сказать. Кому позвонить. Как сформулировать. Что почитать. Раздаю советы быстро, точно, по делу.&lt;/p&gt;
&lt;p&gt;Человек кивает. Уходит.&lt;/p&gt;
&lt;p&gt;Через неделю приходит снова. С тем же вопросом. В новой обёртке.&lt;/p&gt;
&lt;p&gt;И я не понимал почему так.&lt;/p&gt;
&lt;p&gt;Сейчас понимаю. Я отвечал на его слова. А не на его настоящий вопрос - который под словами: страх, сомнение, что-то очень его, во что мой совет даже не пытался попасть.&lt;/p&gt;
&lt;h2 id="что-меняется"&gt;Что меняется
&lt;/h2&gt;&lt;p&gt;Учусь делать другое.&lt;/p&gt;
&lt;p&gt;Не выдавать ответ. Задавать вопросы, от которых человек сам видит свой блок. Что для него важно. Что он уже пробовал. Что его держит. Что станет первым шагом.&lt;/p&gt;
&lt;p&gt;Это медленнее. Менее эффектно. И сложнее, чем выдать ответ за тридцать секунд.&lt;/p&gt;
&lt;p&gt;Но самое интересное и самое сложное - дальше.&lt;/p&gt;
&lt;p&gt;Когда у человека загорается лампочка - &amp;ldquo;Ага! Я понял!&amp;rdquo; - это не финиш. Это эмоциональный всплеск. Через два дня он рассасывается, и человек остаётся с тем же вопросом, что в начале.&lt;/p&gt;
&lt;p&gt;Профессионализм коуча, как я его сейчас вижу, - не отпустить на инсайте. Дойти с человеком до конкретного следующего шага. Проверенного на его собственные грабли. Чтобы у него остался не пик эмоции, а план, который работает без меня.&lt;/p&gt;
&lt;h2 id="где-мой-компас"&gt;Где мой компас
&lt;/h2&gt;&lt;p&gt;И вот тут связалось.&lt;/p&gt;
&lt;p&gt;AI даёт ответы за секунды. Я давал ответы за минуты. Это - то, что заменяется.&lt;/p&gt;
&lt;p&gt;Что не заменяется - умение задать вопрос, от которого человек видит свой реальный блок. И не отпустить, пока у него не сложился рабочий шаг.&lt;/p&gt;
&lt;p&gt;И вот это - точка, на которую можно опираться. Не на знания. Не на ответы. На умение задать вопрос и довести человека до его собственного шага.&lt;/p&gt;
&lt;p&gt;И это, пожалуй, главное, что я унесу из учёбы на коуча в свою работу архитектора. Архитектура систем и архитектура мышления - это один навык, только субстрат разный.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Когда вам в последний раз помог не совет, а правильно поставленный вопрос?&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>AI Agent Linter Ecosystem: Quality, Cost and Safety Control</title><link>https://mshogin.com/blog/ai-linter-ecosystem/</link><pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/ai-linter-ecosystem/</guid><description>&lt;h2 id="the-problem"&gt;The Problem
&lt;/h2&gt;&lt;p&gt;AI agents write code fast, but speed comes at a cost. Literally - tokens cost money. And figuratively - code quality degrades without oversight.&lt;/p&gt;
&lt;p&gt;I hit three problems at once:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Architecture degrades&lt;/strong&gt; - agents write working code that violates layer boundaries, creates circular dependencies and god classes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Costs grow&lt;/strong&gt; - complex prompts go to Opus at $15/1M tokens when Haiku at $0.80 would suffice&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content isn&amp;rsquo;t filtered&lt;/strong&gt; - production prompts contain things that shouldn&amp;rsquo;t be there&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each problem has its own tool. But when the tools work together, they amplify each other.&lt;/p&gt;
&lt;h2 id="the-pipeline"&gt;The Pipeline
&lt;/h2&gt;&lt;p&gt;Every request passes through a chain of linters, each responsible for its domain:&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph LR
A[Prompt] --&gt; B[seclint]
B --&gt;|safe| C[promptlint]
B --&gt;|blocked| X[Reject]
C --&gt;|haiku| D1[Agent: Haiku]
C --&gt;|sonnet| D2[Agent: Sonnet]
C --&gt;|opus| D3[Agent: Opus]
D1 --&gt; E[archlint]
D2 --&gt; E
D3 --&gt; E
E --&gt;|pass| F[costlint]
E --&gt;|fail| C
F --&gt; G[Done]
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;seclint&lt;/strong&gt; - checks content safety (6+/12+/16+/18+ ratings)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;promptlint&lt;/strong&gt; - scores complexity, picks the model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent&lt;/strong&gt; - executes the task on the selected model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;archlint&lt;/strong&gt; - validates the result for architecture violations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;costlint&lt;/strong&gt; - records cost, tracks cache hit rate&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If archlint rejects the result, the task escalates to a more powerful model. costlint records the escalation cost.&lt;/p&gt;
&lt;h2 id="the-tools"&gt;The Tools
&lt;/h2&gt;&lt;h3 id="archlint---architecture-linter"&gt;archlint - Architecture Linter
&lt;/h3&gt;&lt;p&gt;Scans Go projects for structural violations.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;archlint scan --format json ./project/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;What it finds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Layer violations (handler calls repository directly)&lt;/li&gt;
&lt;li&gt;God classes (&amp;gt;20 methods or &amp;gt;15 dependencies)&lt;/li&gt;
&lt;li&gt;Circular dependencies&lt;/li&gt;
&lt;li&gt;Interface Segregation violations (interfaces &amp;gt;5 methods)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Metrics: fan-out, coupling (Ca/Ce), component and link counts.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;mshogin/archlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="promptlint---complexity-based-router"&gt;promptlint - Complexity-Based Router
&lt;/h3&gt;&lt;p&gt;Scores prompt complexity and picks the model. No LLM, pure metrics, &amp;lt;10ms.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Fix typo in README&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; promptlint analyze --output-model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# haiku&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Design microservices with CQRS&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; promptlint analyze --output-model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# opus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Signals: length, sentence count, domain keywords, action type (fix/create/refactor), code presence.&lt;/p&gt;
&lt;p&gt;Integrates with ccproxy for real Claude Code request routing through a proxy.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/promptlint" target="_blank" rel="noopener"
&gt;mikeshogin/promptlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="costlint---token-cost-analysis"&gt;costlint - Token Cost Analysis
&lt;/h3&gt;&lt;p&gt;Tracks spending, analyzes caching, runs A/B tests between models.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;costlint report --source telemetry.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cost Report:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Total requests: 342
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; By model:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; opus: 48 requests, ~$12.60
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sonnet: 195 requests, ~$6.50
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; haiku: 99 requests, ~$0.44
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; With optimal routing: ~$8.20 (savings: 58%)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cache metrics: hit rate, block reuse, content entropy, Jaccard similarity.
A/B testing: 30/30/40 traffic split, per-group cost and quality metrics.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/costlint" target="_blank" rel="noopener"
&gt;mikeshogin/costlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="seclint--promptsec---content-filter"&gt;seclint / promptsec - Content Filter
&lt;/h3&gt;&lt;p&gt;Age ratings for prompts: 6+, 12+, 16+, 18+.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Help with math homework&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; seclint rate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# {&amp;#34;rating&amp;#34;: &amp;#34;6+&amp;#34;, &amp;#34;safe&amp;#34;: true}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Explain SQL injection for security course&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; seclint rate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# {&amp;#34;rating&amp;#34;: &amp;#34;16+&amp;#34;, &amp;#34;safe&amp;#34;: true, &amp;#34;flags&amp;#34;: [&amp;#34;security_tools&amp;#34;]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Considers educational context - explaining SQL injection for a security course gets 16+ instead of 18+.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/seclint" target="_blank" rel="noopener"
&gt;mikeshogin/seclint&lt;/a&gt; / &lt;a class="link" href="https://github.com/mikeshogin/promptsec" target="_blank" rel="noopener"
&gt;mikeshogin/promptsec&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="shared-principles"&gt;Shared Principles
&lt;/h2&gt;&lt;p&gt;All tools follow the same rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt; - single stack, single build&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No LLM&lt;/strong&gt; - pure metrics, regex, keyword matching. &amp;lt;10ms per request&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI + HTTP&lt;/strong&gt; - each tool works as a command and as a server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSONL telemetry&lt;/strong&gt; - unified log format for analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipeline-friendly&lt;/strong&gt; - exit codes, stdout, pipes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="numbers"&gt;Numbers
&lt;/h2&gt;&lt;p&gt;On test workload (342 requests over a week):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Token spending&lt;/td&gt;
&lt;td&gt;$19.54&lt;/td&gt;
&lt;td&gt;$8.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture violations&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests to expensive model&lt;/td&gt;
&lt;td&gt;100% opus&lt;/td&gt;
&lt;td&gt;14% opus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing latency&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&amp;lt;10ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;58% cost savings without quality loss - simple tasks go to Haiku, architecture tasks stay on Opus.&lt;/p&gt;
&lt;h2 id="orchestration"&gt;Orchestration
&lt;/h2&gt;&lt;p&gt;The tools work autonomously, but deliver maximum impact together. For orchestration we use &lt;a class="link" href="https://github.com/kgatilin/myhome" target="_blank" rel="noopener"
&gt;myhome&lt;/a&gt; - daemon-based AI agent management with workflow stages and scheduled tasks.&lt;/p&gt;
&lt;p&gt;The stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;myhome launches agents&lt;/li&gt;
&lt;li&gt;promptlint picks the model (pre-route hook)&lt;/li&gt;
&lt;li&gt;archlint validates output (quality gate stage)&lt;/li&gt;
&lt;li&gt;costlint tracks cost (telemetry consumer)&lt;/li&gt;
&lt;li&gt;seclint filters incoming prompts (pre-filter)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="get-started"&gt;Get Started
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install all tools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mshogin/archlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/promptlint/cmd/promptlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/costlint/cmd/costlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/seclint/cmd/seclint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Start routing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;promptlint serve &lt;span class="m"&gt;8090&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;seclint serve &lt;span class="m"&gt;8091&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check architecture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;archlint scan --format json ./my-project/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# View costs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;costlint report --source ~/.promptlint/telemetry.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="links"&gt;Links
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;archlint&lt;/a&gt; - architecture linter&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/promptlint" target="_blank" rel="noopener"
&gt;promptlint&lt;/a&gt; - complexity router&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/costlint" target="_blank" rel="noopener"
&gt;costlint&lt;/a&gt; - cost analysis&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/seclint" target="_blank" rel="noopener"
&gt;seclint&lt;/a&gt; / &lt;a class="link" href="https://github.com/mikeshogin/promptsec" target="_blank" rel="noopener"
&gt;promptsec&lt;/a&gt; - content filter&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kgatilin/myhome" target="_blank" rel="noopener"
&gt;myhome&lt;/a&gt; - agent orchestration&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/ECOSYSTEM.md" target="_blank" rel="noopener"
&gt;ECOSYSTEM.md&lt;/a&gt; - integration map&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Three blockers that prevent technical leaders from growing</title><link>https://mshogin.com/blog/leadership-blockers/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/leadership-blockers/</guid><description>&lt;img src="https://mshogin.com/blog/leadership-blockers/cover.en.svg" alt="Featured image of post Three blockers that prevent technical leaders from growing" /&gt;&lt;p&gt;AI is changing IT faster than we can adapt. Roles are transforming. Skills that paid well yesterday are losing value today.&lt;/p&gt;
&lt;p&gt;To maintain your standard of living, you need to grow. But growth doesn&amp;rsquo;t stall because of technology. Not because of your stack. Not because of certifications.&lt;/p&gt;
&lt;p&gt;It stalls because of how you think.&lt;/p&gt;
&lt;p&gt;Strong professionals get stuck. Not because they lack knowledge. But because there are internal blockers that are hard to see on your own.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been working with system architecture for over fifteen years. And in recent years I&amp;rsquo;ve noticed: the most serious bugs aren&amp;rsquo;t in code. They&amp;rsquo;re in the heads of people who write that code and manage those who write it.&lt;/p&gt;
&lt;p&gt;Here are three patterns I see most often. In others. And in myself.&lt;/p&gt;
&lt;h2 id="blocker-1-territory-defense"&gt;Blocker 1: Territory defense
&lt;/h2&gt;&lt;p&gt;Every leader has a zone of responsibility. And any entry into it feels like an attack. It&amp;rsquo;s instinct - like a predator patrolling its boundaries.&lt;/p&gt;
&lt;h3 id="what-it-looks-like"&gt;What it looks like
&lt;/h3&gt;&lt;p&gt;Imagine this. You&amp;rsquo;re an architect. A system analyst on your team starts making architectural decisions independently. Doing a decent job, but without checking with you. You see the result - the decisions work, but you feel an irritation inside that&amp;rsquo;s hard to explain rationally.&lt;/p&gt;
&lt;p&gt;In a meeting, you start pushing back. Not because the decision was bad - but because it was made without you. Officially you&amp;rsquo;re talking about quality and process. In reality, you&amp;rsquo;re defending territory.&lt;/p&gt;
&lt;p&gt;Another example. A team lead notices that a senior on the team is starting to take on architectural questions. Instead of giving space and helping them grow, the lead tightens control. More reviews. More approvals. More questions like &amp;ldquo;did you think about&amp;hellip;&amp;rdquo;. Officially - concern for quality. In reality - fear of becoming unnecessary.&lt;/p&gt;
&lt;h3 id="why-this-is-a-blocker"&gt;Why this is a blocker
&lt;/h3&gt;&lt;p&gt;The problem isn&amp;rsquo;t defense. Protecting boundaries is normal.&lt;/p&gt;
&lt;p&gt;The problem is HOW you defend them. From confidence in your abilities - or from fear that something will be taken away? The first is leadership. The second is aggression that people feel. And they leave.&lt;/p&gt;
&lt;p&gt;If we draw an analogy with systems: it&amp;rsquo;s like a microservice that instead of providing an API for interaction, closes all ports and returns 403 to every request. Technically it works. But the system around it degrades.&lt;/p&gt;
&lt;h3 id="the-skill"&gt;The skill
&lt;/h3&gt;&lt;p&gt;Distinguish real threats from phantom ones. One question to yourself: &amp;ldquo;am I protecting quality right now - or protecting my ego?&amp;rdquo;&lt;/p&gt;
&lt;h2 id="blocker-2-craving-recognition"&gt;Blocker 2: Craving recognition
&lt;/h2&gt;&lt;p&gt;This is really about feedback.&lt;/p&gt;
&lt;h3 id="what-it-looks-like-1"&gt;What it looks like
&lt;/h3&gt;&lt;p&gt;You did excellent work. Designed a system that handles the load. Ran a review process that raised code quality across the team. Solved a problem that nobody could crack for six months.&lt;/p&gt;
&lt;p&gt;And silence. Nobody came over and said &amp;ldquo;great work.&amp;rdquo; Your manager is quiet. The team took the result for granted.&lt;/p&gt;
&lt;p&gt;In that silence, your brain starts filling in the gaps: &amp;ldquo;I must be doing a bad job.&amp;rdquo; Or worse: &amp;ldquo;they don&amp;rsquo;t value what I do.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;A familiar story: an architect built an API review process for system analysts. Specification quality went up. Integration-phase bugs went down. But the manager never once said &amp;ldquo;good work.&amp;rdquo; At some point the architect started wondering - was it even worth spending time on this.&lt;/p&gt;
&lt;p&gt;Another example. A senior developer spent a month refactoring a critical module. Code got cleaner, tests more reliable, deploy time cut in half. At the retro, nobody even mentioned it. The senior started losing motivation - not because the work was meaningless, but because nobody noticed.&lt;/p&gt;
&lt;h3 id="why-this-is-a-blocker-1"&gt;Why this is a blocker
&lt;/h3&gt;&lt;p&gt;In adult life, nobody will come and say &amp;ldquo;well done.&amp;rdquo; Parents did that. At work - silence. And in that silence, your brain starts making things up.&lt;/p&gt;
&lt;p&gt;Looking at it as a system: you have no observability for your own value. No metrics, no dashboard, no alerts. You&amp;rsquo;re working blind and relying on a single indicator - external praise. And that indicator is unreliable. It depends on your manager&amp;rsquo;s mood, on company culture, on a thousand factors you don&amp;rsquo;t control.&lt;/p&gt;
&lt;h3 id="the-skill-1"&gt;The skill
&lt;/h3&gt;&lt;p&gt;Either learn to ask for feedback - that&amp;rsquo;s not weakness, it&amp;rsquo;s maturity. Or build an internal foundation that doesn&amp;rsquo;t depend on other people&amp;rsquo;s words.&lt;/p&gt;
&lt;p&gt;Practically: keep your own achievement log. Once a week, write down what you did and what effect it had. In six months you&amp;rsquo;ll have an objective picture - regardless of whether your manager noticed.&lt;/p&gt;
&lt;h2 id="blocker-3-the-experience-trap"&gt;Blocker 3: The experience trap
&lt;/h2&gt;&lt;p&gt;Deep experience creates an illusion: &amp;ldquo;I know more, therefore I&amp;rsquo;m owed something.&amp;rdquo;&lt;/p&gt;
&lt;h3 id="what-it-looks-like-2"&gt;What it looks like
&lt;/h3&gt;&lt;p&gt;A meeting. You&amp;rsquo;re the most experienced person in the room. A junior proposes a solution. You see problems in it. And instead of asking a question - &amp;ldquo;what happens at 10x load?&amp;rdquo; - you say: &amp;ldquo;no, that&amp;rsquo;s not how it&amp;rsquo;s done, I&amp;rsquo;ve been doing this for ten years and I know.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Technically you&amp;rsquo;re right. The solution might not handle the load. But you killed two things: the junior&amp;rsquo;s initiative and the team&amp;rsquo;s ability to learn to think independently.&lt;/p&gt;
&lt;p&gt;Another example. An experienced team lead joins a new team. They have three successful projects behind them using a specific stack. The team uses a different approach. Instead of understanding why that approach was chosen, the lead starts pushing their own. Not because it&amp;rsquo;s better - but because it&amp;rsquo;s familiar. And because accepting someone else&amp;rsquo;s approach means accepting that your experience isn&amp;rsquo;t universal.&lt;/p&gt;
&lt;p&gt;I catch myself doing this. Sometimes I push with experience instead of listening. And every time I catch myself, I ask: am I teaching right now - or proving?&lt;/p&gt;
&lt;h3 id="why-this-is-a-blocker-2"&gt;Why this is a blocker
&lt;/h3&gt;&lt;p&gt;The world is transforming. Old patterns are breaking down. In the age of AI, yesterday&amp;rsquo;s expert is learning from scratch today. Experience is valuable, but it&amp;rsquo;s not currency to exchange for submission.&lt;/p&gt;
&lt;p&gt;As a system analogy: it&amp;rsquo;s a legacy service with hardcoded configuration. It used to work perfectly. But the world around it changed, and it still expects requests in the old format. And instead of adapting its API, it demands that everything else adapts to it.&lt;/p&gt;
&lt;h3 id="the-skill-2"&gt;The skill
&lt;/h3&gt;&lt;p&gt;Treat colleagues as equals. Regardless of the experience gap. This doesn&amp;rsquo;t mean ignoring your experience - it means sharing it through questions, not through pressure.&lt;/p&gt;
&lt;h2 id="three-blockers-three-skills-none-about-technology"&gt;Three blockers. Three skills. None about technology
&lt;/h2&gt;&lt;p&gt;Territory defense, craving recognition, the experience trap. These patterns can&amp;rsquo;t be solved by reading books or taking courses. They&amp;rsquo;re embedded in your thinking architecture so deeply that they&amp;rsquo;re hard to see on your own.&lt;/p&gt;
&lt;p&gt;Like in any project: to see architectural problems, you need an outside perspective. The one inside the system sees individual symptoms. The one outside sees the pattern.&lt;/p&gt;
&lt;p&gt;Leadership starts not with the architecture of systems, but with the architecture of thinking. And if you feel stuck - maybe it&amp;rsquo;s not that you don&amp;rsquo;t know enough. Maybe it&amp;rsquo;s time to look at your thinking as a system and run an honest audit on it.&lt;/p&gt;</description></item><item><title>Фаулер про LLM и разработчиков: cognitive debt, supervisory programming и кто на самом деле под ударом</title><link>https://mshogin.com/blog/fowler-llm-developers/</link><pubDate>Fri, 13 Feb 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/fowler-llm-developers/</guid><description>&lt;img src="https://mshogin.com/cover.svg" alt="Featured image of post Фаулер про LLM и разработчиков: cognitive debt, supervisory programming и кто на самом деле под ударом" /&gt;&lt;p&gt;Мартин Фаулер опубликовал заметки с встречи senior-разработчиков, посвященной LLM. Не очередной хайп про &amp;ldquo;AI заменит всех&amp;rdquo; - а трезвый разбор от людей, которые пишут код десятилетиями.&lt;/p&gt;
&lt;p&gt;Несколько тезисов зацепили настолько, что захотелось разобрать их подробнее. С примерами из собственной практики.&lt;/p&gt;
&lt;h2 id="mid-level-под-ударом-а-не-джуны"&gt;Mid-level под ударом, а не джуны
&lt;/h2&gt;&lt;p&gt;Обычно все переживают за junior-разработчиков: их-то заменят первыми. Фаулер с группой пришли к обратному выводу.&lt;/p&gt;
&lt;p&gt;Джуны адаптивны. Они росли с LLM, умеют ими пользоваться, открыты к новому. Сеньоры понимают архитектуру, видят систему целиком, эффективно управляют агентами - примерно как управляют джунами.&lt;/p&gt;
&lt;p&gt;А mid-level? Они сформировались без LLM, но еще не набрали достаточно опыта, чтобы эффективно ими управлять. Застряли между двумя мирами.&lt;/p&gt;
&lt;p&gt;На практике я вижу это так: mid-level разработчик умеет писать код. Хорошо умеет. Но когда LLM генерирует код быстрее - &amp;ldquo;умение писать код&amp;rdquo; перестает быть конкурентным преимуществом. А понимание &amp;ldquo;зачем этот код нужен&amp;rdquo;, &amp;ldquo;как он вписывается в систему&amp;rdquo;, &amp;ldquo;какие trade-offs мы принимаем&amp;rdquo; - это уже территория сеньоров.&lt;/p&gt;
&lt;p&gt;Один из участников рассказал показательную историю: сеньоры в их компании были резко против LLM. Но когда их заставили поработать руками - треть моментально стала pro-LLM. Практический опыт важнее теоретических страхов. Как пошутили на встрече, некоторые негативные мнения о LLM &amp;ldquo;остались в январе&amp;rdquo;.&lt;/p&gt;
&lt;h3 id="что-делать-mid-level"&gt;Что делать mid-level
&lt;/h3&gt;&lt;p&gt;Если ты mid-level - у тебя есть окно. Не в том, чтобы учиться промптить. А в том, чтобы быстрее набирать архитектурное мышление: понимание систем, trade-offs, бизнес-контекста. То, что LLM пока делает плохо.&lt;/p&gt;
&lt;h2 id="cognitive-debt-опаснее-technical-debt"&gt;Cognitive debt опаснее technical debt
&lt;/h2&gt;&lt;p&gt;Это, на мой взгляд, самый ценный тезис. Фаулер ссылается на исследование Margaret-Anne Storey и проводит параллель с technical debt.&lt;/p&gt;
&lt;p&gt;Её кейс: студенческие команды строили продукт, генерируя код с помощью LLM. К 7-8 неделе одна команда уперлась в стену - любое изменение ломало что-то неожиданное. Сначала обвинили технический долг. Но реальная проблема была в другом: никто в команде не мог объяснить, почему были приняты те или иные решения. Shared understanding - общее понимание системы - фрагментировалось и исчезло.&lt;/p&gt;
&lt;p&gt;Фаулер разделяет это на два слоя:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cruft&lt;/strong&gt; (хлам в коде) -&amp;gt; в когнитивной сфере это &lt;strong&gt;ignorance&lt;/strong&gt; (невежество) - незнание кода и домена&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debt&lt;/strong&gt; (долг как метафора стоимости) -&amp;gt; либо платишь &amp;ldquo;проценты&amp;rdquo; (каждое изменение дороже), либо &amp;ldquo;гасишь тело&amp;rdquo; (инвестируешь в понимание)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это точное попадание в то, что я вижу при приемке проектов. Не раз сталкивался с ситуацией: код написан грамотно, тесты есть, линтеры проходят - но никто не может объяснить, почему выбрана такая декомпозиция сервисов. Или зачем нужен этот промежуточный слой. Документация говорит &amp;ldquo;что&amp;rdquo;, но не говорит &amp;ldquo;зачем&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;С LLM-агентами cognitive debt будет масштабироваться: код генерируется быстрее, чем команда успевает его осмыслить. Скорость создания кода перестает быть ограничителем. Ограничителем становится скорость понимания.&lt;/p&gt;
&lt;h3 id="как-с-этим-работать"&gt;Как с этим работать
&lt;/h3&gt;&lt;p&gt;Несколько практик, которые помогают:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ADR (Architecture Decision Records)&lt;/strong&gt; - фиксируем не &amp;ldquo;что решили&amp;rdquo;, а &amp;ldquo;почему решили и какие варианты отвергли&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Коучинговые вопросы на ревью&lt;/strong&gt; - вместо &amp;ldquo;используй Strategy pattern&amp;rdquo; спрашивать &amp;ldquo;какие варианты ты рассмотрел? какие trade-offs?&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Обязательный контекст в PR&lt;/strong&gt; - не просто diff, а &amp;ldquo;зачем&amp;rdquo; это изменение нужно&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Если LLM генерирует код - пусть генерирует и ADR к нему. Хотя бы черновик для ревью.&lt;/p&gt;
&lt;h2 id="devex-и-agent-experience---это-круг"&gt;DevEx и Agent Experience - это круг
&lt;/h2&gt;&lt;p&gt;Laura Tacho сказала фразу, которая заслуживает стать мемом:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Venn Diagram of Developer Experience and Agent Experience is a circle&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Всё, за что годами боролись в developer experience - гладкий тулинг, понятная документация, чистая модульность, осмысленные имена - оказывается, помогает и LLM-агентам. Хорошая модульность и descriptive naming так же полезны для трансформера, как и для &amp;ldquo;более мягких нейронных сетей&amp;rdquo; (мозгов).&lt;/p&gt;
&lt;p&gt;И горькая ирония: менеджмент готов инвестировать в &amp;ldquo;smooth path для LLM&amp;rdquo;, но не готов был делать это для людей. Экзекьютивам не жалко денег на роботов, но жалко на разработчиков.&lt;/p&gt;
&lt;p&gt;Из моего опыта: чистая архитектура с явными зависимостями, маленькими интерфейсами и четкими слоями - это ровно то, что позволяет LLM-агенту эффективно работать с кодобазой. Когда я настраивал Claude Code для работы со своими проектами, разница была заметна сразу: в проекте с чистой архитектурой агент находит нужный контекст за секунды. В проекте-монолите с неявными зависимостями - путается, галлюцинирует, предлагает изменения не в тех файлах.&lt;/p&gt;
&lt;p&gt;Вывод неутешительный и простой: если ваша кодобаза - хаос для людей, она будет хаосом и для агентов. Инвестиции в DevEx теперь имеют двойной ROI.&lt;/p&gt;
&lt;h2 id="supervisory-programming-и-менеджерское-выгорание"&gt;Supervisory programming и менеджерское выгорание
&lt;/h2&gt;&lt;p&gt;Камилла Фурнье заметила:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The part of &amp;ldquo;everyone becomes a manager&amp;rdquo; in AI that I didn&amp;rsquo;t really think about until now was the mental fatigue of context switching&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Тренд &amp;ldquo;один программист управляет несколькими агентами&amp;rdquo; несет с собой ровно ту же болезнь, от которой годами страдают менеджеры: усталость от переключения контекста. Держать в голове 5 параллельных задач, ревьюить результаты из разных контекстов, ловить ошибки в коде, который ты не писал - это менеджмент, а не программирование.&lt;/p&gt;
&lt;p&gt;Фаулер осторожно предполагает, что два человека + агенты могут быть эффективнее, чем один человек + много агентов. Парное программирование нового формата: два мозга ловят ошибки &amp;ldquo;джинна&amp;rdquo; лучше, чем один.&lt;/p&gt;
&lt;p&gt;Мне эта мысль близка. В коучинге есть концепция: сам себе коучем быть нельзя, нужен внешний наблюдатель. С кодом похоже - второй человек видит то, что ты пропустил. А когда агенты генерируют код быстрее, чем один человек может ревьюить - второй мозг не роскошь, а необходимость.&lt;/p&gt;
&lt;h3 id="workload-creep"&gt;Workload creep
&lt;/h3&gt;&lt;p&gt;Фаулер также цитирует исследование из Harvard Business Review: в компании на 200 человек после внедрения AI сотрудники стали работать быстрее, брать больше задач, работать больше часов - часто без просьбы. Звучит как мечта менеджера. Но за первоначальным всплеском приходит: cognitive fatigue, выгорание, ухудшение качества решений.&lt;/p&gt;
&lt;p&gt;Это классический паттерн. Новый инструмент дает эйфорию -&amp;gt; берешь больше -&amp;gt; не замечаешь, как нагрузка выросла -&amp;gt; burnout.&lt;/p&gt;
&lt;h2 id="размер-команд"&gt;Размер команд
&lt;/h2&gt;&lt;p&gt;Уменьшатся ли команды? Фаулер склоняется к &amp;ldquo;нет&amp;rdquo;. Two-pizza teams (5-8 человек) останутся примерно того же размера - но будут делать значительно больше. Есть что-то фундаментальное в размере команды, что балансирует выгоды сотрудничества с издержками координации. LLM не едят пиццу, но они и не добавляют в team dynamics.&lt;/p&gt;
&lt;h2 id="будущее-ide"&gt;Будущее IDE
&lt;/h2&gt;&lt;p&gt;Отдельная тема - будущее IDE. LLM не заменяют IDE, а встраиваются в них. Переименовать функцию через LLM - это как забивать гвоздь микроскопом. Но LLM может оркестрировать инструменты IDE: увидеть, что &amp;ldquo;person&amp;rdquo; нужно переименовать в &amp;ldquo;contact&amp;rdquo; во всех контекстах (функции, поля, документация, тесты), и использовать детерминистические рефакторинги IDE для каждого из них.&lt;/p&gt;
&lt;p&gt;Мне как пользователю Emacs это особенно резонирует. IDE - это мощный инструмент, но мало кто использует его на полную. LLM может стать тем слоем, который знает возможности IDE лучше пользователя и подсказывает, когда использовать LLM, когда - детерминистический рефакторинг, а когда - их комбинацию.&lt;/p&gt;
&lt;h2 id="итого"&gt;Итого
&lt;/h2&gt;&lt;p&gt;Главные мысли из текста Фаулера:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mid-level под ударом&lt;/strong&gt; - не джуны, как все думали. Окно для роста: быстрее набирать архитектурное мышление&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cognitive debt &amp;gt; technical debt&lt;/strong&gt; - с LLM код генерируется быстрее, чем осмысляется. Ограничитель теперь - понимание, а не написание&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DevEx = Agent Experience&lt;/strong&gt; - инвестиции в чистую архитектуру дают двойной ROI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supervisory programming = менеджерское выгорание&lt;/strong&gt; - context switching утомляет. Пара людей + агенты может быть лучше одиночки + много агентов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workload creep&lt;/strong&gt; - эйфория от AI -&amp;gt; перегрузка -&amp;gt; burnout. Классика&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Текст Фаулера ценен тем, что он не про хайп и не про страх. Он про трезвую оценку: что меняется, что остается, и какие новые проблемы приходят вместе с новыми возможностями.&lt;/p&gt;
&lt;p&gt;А ты замечаешь cognitive debt в своих проектах?&lt;/p&gt;</description></item><item><title>Архитектура памяти для AI-агентов: как я научил Claude Code помнить</title><link>https://mshogin.com/blog/memory-architecture-for-ai-agents/</link><pubDate>Wed, 11 Feb 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/memory-architecture-for-ai-agents/</guid><description>&lt;img src="https://mshogin.com/blog/memory-architecture-for-ai-agents/cover.svg" alt="Featured image of post Архитектура памяти для AI-агентов: как я научил Claude Code помнить" /&gt;&lt;h2 id="боль-агент-с-амнезией"&gt;Боль: агент с амнезией
&lt;/h2&gt;&lt;p&gt;Каждый, кто работает с AI-агентами, знает ощущение: ты объяснил контекст проекта, показал структуру, обсудил решения - а в следующей сессии агент всё забыл. Опять здрасьте. Опять &amp;ldquo;расскажите про ваш проект&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Это как работать с архитектором, у которого каждое утро стирается память. Он талантлив, быстр, но каждый день - новый человек.&lt;/p&gt;
&lt;p&gt;У меня 12+ активных контекстов: рабочие проекты (Wildberries), личные проекты (aitrader, archlint), блог, коучинговая практика, обучение, целеполагание. Переключение между ними без памяти превращалось в ритуал: 5-10 минут на &amp;ldquo;загрузку контекста&amp;rdquo; в начале каждой сессии.&lt;/p&gt;
&lt;p&gt;Стало ясно: нужна архитектура памяти.&lt;/p&gt;
&lt;h2 id="как-устроена-человеческая-память"&gt;Как устроена человеческая память
&lt;/h2&gt;&lt;p&gt;Прежде чем проектировать, я посмотрел на то, как работает память у людей. Параллельно с архитектурой я изучаю коучинг - и там постоянно всплывает тема того, как люди обрабатывают информацию. Заметил структурное сходство.&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart TD
A["Входящие данные"] --&gt; B["Рабочая память\n(Short-Term)\nАктивные задачи,\nтекущий контекст"]
B --&gt; C{"Фильтр ценности\n(еженедельный ревью)"}
C --&gt;|"Ценно"| D["Долговременная память\n(Long-Term)\nПаттерны, принципы, уроки"]
C --&gt;|"Обработано"| E["Архив\n(забыто, но доступно)"]
&lt;/div&gt;
&lt;p&gt;У людей так же:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Рабочая память&lt;/strong&gt; (Short-Term) - то, с чем работаешь прямо сейчас. Ограничена: ~7 элементов одновременно. Через 3-6 месяцев без обращения - забывается.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Долговременная память&lt;/strong&gt; (Long-Term) - дистиллированные знания. Не &amp;ldquo;что я делал во вторник&amp;rdquo;, а &amp;ldquo;какой паттерн я увидел за три месяца работы&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Архив&lt;/strong&gt; - не удалено, но не на поверхности. Доступно при целенаправленном поиске.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ключевой момент: переход из Short-Term в Long-Term - не автоматический. Нужна осознанная обработка. В коучинге это рефлексия. В моей системе - еженедельный ревью.&lt;/p&gt;
&lt;h2 id="архитектура-решения"&gt;Архитектура решения
&lt;/h2&gt;&lt;h3 id="три-уровня-памяти"&gt;Три уровня памяти
&lt;/h3&gt;&lt;p&gt;Я реализовал три уровня, зеркалирующих человеческую модель:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/my/org-roam/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- Short-Term-Memory/ # Рабочая память (3-6 месяцев)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Wildberries/ # Рабочий контекст
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Coaching/ # Коучинговые сессии
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- daily/ # Ежедневные заметки
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- todos.md # Задачи
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- Long-Term-Memory/ # Долговременная память
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Coaching/ # Методики, паттерны, кейсы
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Architecture/ # Архитектурные решения
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Posts/ # Публикации
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| +-- Personal/ # Личные принципы
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;+-- Archive/ # Архив (по месяцам)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +-- 2026/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +-- 01-January/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +-- 02-February/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Short-Term&lt;/strong&gt; - inbox для всего нового. Сырые заметки, текущие задачи, эксперименты. Максимум 50 активных файлов. Если больше - пора делать ревью.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Long-Term&lt;/strong&gt; - база знаний. Сюда попадает только то, что прошло фильтр ценности:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Переиспользуемость (применимо 3+ раз)&lt;/li&gt;
&lt;li&gt;Обучающая ценность (ага-момент, важная ошибка)&lt;/li&gt;
&lt;li&gt;Референсная ценность (пример для копирования)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Archive&lt;/strong&gt; - завершенные проекты, обработанные заметки. Не удалено, но убрано с глаз.&lt;/p&gt;
&lt;h3 id="контексты-переключение-за-секунду"&gt;Контексты: переключение за секунду
&lt;/h3&gt;&lt;p&gt;Вторая проблема - переключение между проектами. Решение: система контекстов.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;contexts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;coaching&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;coaching&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Коучинговые сессии и практика развития&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/my/coaching&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;short_term&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/my/org-roam/Short-Term-Memory/Coaching&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;long_term&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/my/org-roam/Long-Term-Memory/Coaching&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;archlint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;archlint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ArchLint - линтер архитектуры Go проектов&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/my/archlint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;short_term&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;long_term&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Каждый контекст знает:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;directory&lt;/strong&gt; - рабочая директория проекта&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;memory.short_term&lt;/strong&gt; - где хранить текущие заметки&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;memory.long_term&lt;/strong&gt; - где хранить дистиллированные знания&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Переключение: одна команда &lt;code&gt;/w coaching&lt;/code&gt; - и агент знает где он, что помнить, какие файлы читать.&lt;/p&gt;
&lt;h3 id="индекс-активностей-навигация-по-всему"&gt;Индекс активностей: навигация по всему
&lt;/h3&gt;&lt;p&gt;Контексты решают проблему &amp;ldquo;где я&amp;rdquo;. Но остается вопрос: &amp;ldquo;где искать информацию по теме X?&amp;rdquo;. Для этого - глобальный индекс активностей.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Коучинг / Практика
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Keywords: сессия, клиент, практика, рефлексия
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Файлы:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;-&lt;/span&gt; Практика: ~/my/org-roam/Long-Term-Memory/Coaching/03-Практика/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;-&lt;/span&gt; Гайды сессий: ~/my/org-roam/Long-Term-Memory/Coaching/session-guides/INDEX.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Здоровье и психология
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Keywords: психолог, здоровье, границы, стыд
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Файлы:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;-&lt;/span&gt; Темы: ~/my/org-roam/Long-Term-Memory/Темы для психолога.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Связанные активности: Коучинг / Запросы для проработки
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Принцип работы:&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart TD
A["Промпт пользователя"] --&gt; B["Поиск по keywords\nв memory-index.md"]
B --&gt; C{"Найдена\nактивность?"}
C --&gt;|"Да"| D["Работай в её контексте"]
C --&gt;|"Нет"| E["Спроси пользователя,\nпредложи варианты"]
&lt;/div&gt;
&lt;h3 id="кросс-контекстный-поиск-связи-между-контекстами"&gt;Кросс-контекстный поиск: связи между контекстами
&lt;/h3&gt;&lt;p&gt;Самая интересная архитектурная задача. Информация часто пересекает границы контекстов.&lt;/p&gt;
&lt;p&gt;Пример: тема &amp;ldquo;границы&amp;rdquo; может всплыть в коучинге (запрос клиента), в психологии (тема для терапии), в рабочем контексте (обратная связь коллеге). Как не потерять связь?&lt;/p&gt;
&lt;p&gt;Решение: &lt;strong&gt;кросс-ссылки на уровне глобального индекса&lt;/strong&gt;, а не дублирование информации между контекстными индексами.&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart TD
G["memory-index.md\n(глобальный индекс)"] --&gt; C1["Coaching\nINDEX.md"]
G --&gt; C2["Здоровье\n(файлы)"]
G --&gt; C3["Работа\nINDEX.md"]
G --&gt; C4["..."]
C1 -.-|"кросс-ссылка"| C2
C2 -.-|"кросс-ссылка"| C3
style G fill:#0f3460,color:#fff
style C1 fill:#533483,color:#fff
style C2 fill:#533483,color:#fff
style C3 fill:#533483,color:#fff
style C4 fill:#333,color:#999
&lt;/div&gt;
&lt;p&gt;Правило: каждый контекстный индекс отвечает только за свой контекст. Связь между контекстами - через поле &amp;ldquo;Связанные активности&amp;rdquo; в глобальном индексе.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Кросс-ссылки между активностями
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| Активность A | Активность B | Связь |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|--------------------------|------------------------|-------------------------------------|
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| Коучинг / Запросы | Здоровье и психология | Запрос &lt;span class="ni"&gt;#11&lt;/span&gt; = Тема &lt;span class="ni"&gt;#2&lt;/span&gt; (границы) |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| Семья | Коучинг / Запросы | Запрос &lt;span class="ni"&gt;#3&lt;/span&gt; (темы с супругой) |
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Антипаттерн: дублировать ссылки на &amp;ldquo;Темы для психолога&amp;rdquo; внутри Coaching/INDEX.md. Это нарушает single responsibility - индекс коучинга не должен знать про психологию. Связь - только через глобальный уровень.&lt;/p&gt;
&lt;h2 id="жизненный-цикл-знаний"&gt;Жизненный цикл знаний
&lt;/h2&gt;&lt;p&gt;Данные без обработки - мусор. Система памяти работает, только если есть процесс трансформации.&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart LR
subgraph ST ["Short-Term (сырые данные)"]
A1["Заметки по сессии\nс клиентом X"]
A2["Тикеты проекта\nархитектуры"]
A3["Исследование\nTarjan алгоритма"]
end
subgraph LT ["Long-Term (знания)"]
B1["Паттерн: Работа с\nпрокрастинацией\nчерез ценности"]
B2["ADR-0042: Выбор\nмежду монолитом\nи микросервисами"]
B3["Библиотека\nалгоритмов\nпоиска циклов"]
end
A1 --&gt;|"трансформация"| B1
A2 --&gt;|"трансформация"| B2
A3 --&gt;|"трансформация"| B3
&lt;/div&gt;
&lt;h3 id="критерии-перехода-в-long-term"&gt;Критерии перехода в Long-Term
&lt;/h3&gt;&lt;p&gt;Не всё заслуживает долговременной памяти. Четыре фильтра:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Переиспользуемость&lt;/strong&gt; - применимо 3+ раз (методики, шаблоны, чек-листы)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Обучающая ценность&lt;/strong&gt; - ага-момент, важная ошибка, смена парадигмы&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Референсная ценность&lt;/strong&gt; - пример для копирования (код, кейс, формат)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Паттерн&lt;/strong&gt; - повторяющаяся проблема + решение&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Всё остальное - одноразовые заметки, устаревшие TODO, рутинные логи - удаляется или уходит в архив.&lt;/p&gt;
&lt;h3 id="еженедельный-ревью"&gt;Еженедельный ревью
&lt;/h3&gt;&lt;p&gt;Раз в неделю - 30-40 минут на обработку Short-Term:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Просмотреть файлы за неделю&lt;/li&gt;
&lt;li&gt;Выделить ценное для Long-Term&lt;/li&gt;
&lt;li&gt;Трансформировать: сырые данные -&amp;gt; структурированные знания&lt;/li&gt;
&lt;li&gt;Архивировать обработанное&lt;/li&gt;
&lt;li&gt;Удалить мусор&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Метрики здоровой системы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Short-Term: 30-50 активных файлов&lt;/li&gt;
&lt;li&gt;Long-Term: +2-5 новых записей в неделю&lt;/li&gt;
&lt;li&gt;Archive: регулярное пополнение&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="параллель-с-коучингом"&gt;Параллель с коучингом
&lt;/h2&gt;&lt;p&gt;Когда я проектировал эту систему, я заметил параллели с тем, что изучаю в коучинге.&lt;/p&gt;
&lt;h3 id="short-term--рабочая-осознанность"&gt;Short-Term = Рабочая осознанность
&lt;/h3&gt;&lt;p&gt;Когда человек разбирается в сложной ситуации, он сначала выгружает всё, что на поверхности: факты, эмоции, людей, обстоятельства. Это рабочая память - хаотичная, перегруженная, но актуальная. Short-Term Memory в моей системе работает так же: собирает всё, что сейчас активно, без фильтрации.&lt;/p&gt;
&lt;h3 id="long-term--мудрость-через-рефлексию"&gt;Long-Term = Мудрость через рефлексию
&lt;/h3&gt;&lt;p&gt;Long-Term - это не &amp;ldquo;запомнить всё&amp;rdquo;. Это &amp;ldquo;понять, что важно&amp;rdquo;. Лучшие инсайты приходят не в момент обсуждения, а позже - когда человек рефлексирует и видит паттерн. Еженедельный ревью - это та самая рефлексия, только для базы знаний.&lt;/p&gt;
&lt;h3 id="кросс-контекст--системное-мышление"&gt;Кросс-контекст = Системное мышление
&lt;/h3&gt;&lt;p&gt;Проблема редко живет в одном контексте. Одна и та же тема может всплыть и на работе, и в личных проектах, и в обучении. Кросс-ссылки в системе памяти - это способ видеть одну тему с разных сторон, расширить перспективу.&lt;/p&gt;
&lt;h3 id="architect-of-thinking"&gt;Architect of Thinking
&lt;/h3&gt;&lt;p&gt;Изучая коучинг, я разработал авторский фреймворк на стыке архитектуры и работы с мышлением - Architect of Thinking. Формула:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Контекст -&amp;gt; Цель -&amp;gt; Карта -&amp;gt; Узел -&amp;gt; Решение -&amp;gt; Шаг&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Это ровно то, как архитектор работает с системой: сначала изучи (контекст), определи цель, построй карту, найди bottleneck (узел), спроектируй решение, сделай первый шаг. Тот же подход - к человеческим задачам.&lt;/p&gt;
&lt;h2 id="результаты"&gt;Результаты
&lt;/h2&gt;&lt;h3 id="до-системы-памяти"&gt;До системы памяти:
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;5-10 минут на &amp;ldquo;загрузку контекста&amp;rdquo; каждую сессию&lt;/li&gt;
&lt;li&gt;Потеря решений между сессиями&lt;/li&gt;
&lt;li&gt;Дублирование работы&lt;/li&gt;
&lt;li&gt;Невозможность связать темы между контекстами&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="после"&gt;После:
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Переключение контекста за 1 команду&lt;/li&gt;
&lt;li&gt;Знания накапливаются и структурируются&lt;/li&gt;
&lt;li&gt;Связи между контекстами через кросс-ссылки&lt;/li&gt;
&lt;li&gt;Еженедельный ревью превращает данные в знания&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="что-дальше"&gt;Что дальше
&lt;/h2&gt;&lt;p&gt;Система живая - она развивается вместе с моими проектами. Следующие шаги:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Автоматизация ревью (AI-помощник для еженедельной обработки Short-Term)&lt;/li&gt;
&lt;li&gt;Семантический поиск по Long-Term Memory&lt;/li&gt;
&lt;li&gt;Версионирование знаний (как знания меняются со временем)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Но главный урок не технический. Проектируя память для AI-агента, я лучше понял, как работает моя собственная. И это, пожалуй, самый ценный побочный эффект.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Исходный код и конфигурации описаны для Claude Code (Anthropic CLI). Подход применим к любому AI-агенту с файловой системой.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>How to Onboard 4 Projects into Architectural Oversight Without Losing Your Mind</title><link>https://mshogin.com/notes/how-to-onboard-4-projects-into-architectural-oversight-without-losing-your-mind/</link><pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/how-to-onboard-4-projects-into-architectural-oversight-without-losing-your-mind/</guid><description>&lt;h2 id="the-problem"&gt;The Problem
&lt;/h2&gt;&lt;p&gt;Four projects simultaneously. Different teams, different stacks, unclear functional overlaps. &amp;ldquo;Figure it out&amp;rdquo; - the only instruction.&lt;/p&gt;
&lt;p&gt;Classic situation: manager delegates, architect takes responsibility, but how to onboard projects systematically - unclear.&lt;/p&gt;
&lt;p&gt;Questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where to start?&lt;/li&gt;
&lt;li&gt;What to check first?&lt;/li&gt;
&lt;li&gt;How not to miss critical issues?&lt;/li&gt;
&lt;li&gt;How many days will it take?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keeping everything in your head is pointless. Need a process.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="symptoms-of-chaos"&gt;Symptoms of Chaos
&lt;/h2&gt;&lt;p&gt;When there&amp;rsquo;s no onboarding process, chaos begins.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Symptom 1: Archaeological Excavation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Architect spends a week searching for documentation. Slack, Confluence, Google Drive, wiki - information scattered everywhere. Half is outdated from a year ago. Half needs to be reconstructed from code.&lt;/p&gt;
&lt;p&gt;Result: 5 days wasted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Symptom 2: Unexpected Problems&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A month after onboarding: monitoring doesn&amp;rsquo;t exist, tests don&amp;rsquo;t cover critical paths, CI/CD runs on workarounds. Too late to fix - project already in production.&lt;/p&gt;
&lt;p&gt;Result: Firefighting instead of oversight.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Symptom 3: Team Conflicts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Architect starts changing code without context. Tech Lead resists: &amp;ldquo;We&amp;rsquo;ve been doing it this way for a year, why change?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Result: Loss of trust.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="diagnosis-need-a-system"&gt;Diagnosis: Need a System
&lt;/h2&gt;&lt;p&gt;Problem isn&amp;rsquo;t in projects. Problem is lack of process.&lt;/p&gt;
&lt;p&gt;Project onboarding isn&amp;rsquo;t about code. It&amp;rsquo;s about:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gathering context (business, technical, operational)&lt;/li&gt;
&lt;li&gt;Assessing maturity (architecture, code, processes)&lt;/li&gt;
&lt;li&gt;Aligning expectations (with PM, Tech Lead, team)&lt;/li&gt;
&lt;li&gt;Improvement plan (prioritization and timeline)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Without a formal process, you reinvent the wheel every time.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="solution-6-phase-process"&gt;Solution: 6-Phase Process
&lt;/h2&gt;&lt;p&gt;Studied industry practices (Futurice, TOGAF, Harvard EA) and assembled an onboarding process.&lt;/p&gt;
&lt;h3 id="process-phases"&gt;Process Phases
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Initiation] -&amp;gt; [Kickoff] -&amp;gt; [Info Gathering] -&amp;gt; [Audit] -&amp;gt; [Plan Agreement] -&amp;gt; [Onboarding]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1 day 1-2 hours 3-5 days 3-7 days 1 day ongoing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Total time: &lt;strong&gt;7-14 days&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase-1-initiation-1-day"&gt;Phase 1: Initiation (1 day)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Get basic information and access.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Actions:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Request intro from PM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What&amp;rsquo;s the project?&lt;/li&gt;
&lt;li&gt;What problems does it solve?&lt;/li&gt;
&lt;li&gt;Who&amp;rsquo;s the Tech Lead?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Request access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Repositories (GitHub/GitLab)&lt;/li&gt;
&lt;li&gt;Monitoring (Grafana/Prometheus)&lt;/li&gt;
&lt;li&gt;Documentation (Confluence/Notion)&lt;/li&gt;
&lt;li&gt;CI/CD (Jenkins/GitLab CI)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Schedule kickoff meeting.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Basic project understanding, all access granted.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase-2-kickoff-1-2-hours"&gt;Phase 2: Kickoff (1-2 hours)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Sync with PM and Tech Lead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PM (business context)&lt;/li&gt;
&lt;li&gt;Tech Lead (technical picture)&lt;/li&gt;
&lt;li&gt;Architect (onboarding)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Agenda:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Business context (10 min)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why this project?&lt;/li&gt;
&lt;li&gt;Who are the users?&lt;/li&gt;
&lt;li&gt;What are success metrics?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Technical picture (30 min)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Architecture (components, integrations)&lt;/li&gt;
&lt;li&gt;Stack (languages, frameworks)&lt;/li&gt;
&lt;li&gt;Operations (deployment, monitoring, incidents)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Oversight expectations (20 min)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What&amp;rsquo;s needed from architect?&lt;/li&gt;
&lt;li&gt;How often syncs?&lt;/li&gt;
&lt;li&gt;Code review/Design review?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next steps (10 min)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation gathering&lt;/li&gt;
&lt;li&gt;Audit dates&lt;/li&gt;
&lt;li&gt;Report format&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Everyone aligned, plan agreed.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase-3-information-gathering-3-5-days"&gt;Phase 3: Information Gathering (3-5 days)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Collect everything needed for audit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What we gather:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Documentation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Architecture (C4, ADR)&lt;/li&gt;
&lt;li&gt;API specs (OpenAPI/Swagger)&lt;/li&gt;
&lt;li&gt;Business processes (BPMN)&lt;/li&gt;
&lt;li&gt;Incidents (postmortems)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. Code&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Repo structure&lt;/li&gt;
&lt;li&gt;Test coverage&lt;/li&gt;
&lt;li&gt;Code quality (linters, code review)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. Infrastructure&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CI/CD pipeline&lt;/li&gt;
&lt;li&gt;Deployment (Kubernetes/Docker)&lt;/li&gt;
&lt;li&gt;Monitoring (metrics, alerts)&lt;/li&gt;
&lt;li&gt;Logs (structured, retention)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. Operational&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SLA (uptime, latency)&lt;/li&gt;
&lt;li&gt;Incident history&lt;/li&gt;
&lt;li&gt;Escalation processes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Folder with materials for audit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gathering checklist:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Architecture documentation (C4, ADR)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; API specifications (OpenAPI)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Database schema (ER-diagram)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; CI/CD pipeline (configs)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Monitoring (Grafana dashboards)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Incident history (postmortems)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Test coverage (coverage report)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [ ]&lt;/span&gt; Team processes (code review, standup)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="phase-4-audit-3-7-days"&gt;Phase 4: Audit (3-7 days)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Understand current project state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audit levels:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Level 1: Architecture Overview (1-2 days)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;System structure (components, layers)&lt;/li&gt;
&lt;li&gt;Bounded contexts (if microservices)&lt;/li&gt;
&lt;li&gt;Integrations (sync/async)&lt;/li&gt;
&lt;li&gt;Tech debt map&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Level 2: Deep Dive (2-4 days)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code (smells, complexity, duplicates)&lt;/li&gt;
&lt;li&gt;Tests (coverage, quality, fragility)&lt;/li&gt;
&lt;li&gt;CI/CD (speed, reliability, rollback)&lt;/li&gt;
&lt;li&gt;Monitoring (completeness, alerting, observability)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Level 3: Operational (1 day)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SLA vs actual&lt;/li&gt;
&lt;li&gt;Incidents (frequency, recovery time)&lt;/li&gt;
&lt;li&gt;Team processes (code review, ADR, standups)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Audit tools:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I assembled an audit template together with Claude Code (~3882 lines of config). Read and edited it.&lt;/p&gt;
&lt;p&gt;What resulted:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checklist (11 sections, 80+ items)&lt;/li&gt;
&lt;li&gt;Report template (12 sections)&lt;/li&gt;
&lt;li&gt;Automated validation (215 metrics)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Validation example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Test coverage check&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ archlint validate --template system-audit --project ./my-project
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✓ Test coverage: 78% &lt;span class="o"&gt;(&lt;/span&gt;target: &amp;gt;70%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✗ Critical paths coverage: 45% &lt;span class="o"&gt;(&lt;/span&gt;target: &amp;gt;80%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;✓ CI/CD pipeline: green
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;⚠ Monitoring: missing SLO alerts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Score: 7/10 &lt;span class="o"&gt;(&lt;/span&gt;acceptable with improvements&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Audit result:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Audit Report for {ProjectName}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: YYYY-MM-DD
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Architect: {Name}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Executive Summary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Status: Acceptable with improvements
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Critical issues: 3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Needs attention: 12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Score: 7/10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Critical Issues (P0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;1.&lt;/span&gt; No SLO monitoring
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;2.&lt;/span&gt; Critical path coverage &amp;lt;50%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;3.&lt;/span&gt; Missing ADR process
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Needs Attention (P1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Recommendations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="phase-5-improvement-plan-agreement-1-day"&gt;Phase 5: Improvement Plan Agreement (1 day)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Agree on action plan with team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Format:&lt;/strong&gt; Meeting with PM and Tech Lead (1 hour).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agenda:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Report presentation (30 min)&lt;/li&gt;
&lt;li&gt;Critical issues discussion (20 min)&lt;/li&gt;
&lt;li&gt;Improvement plan (10 min)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Three plan types depending on state:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plan 1: Stable Project&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Non-critical issues&lt;/li&gt;
&lt;li&gt;Quarterly improvement plan&lt;/li&gt;
&lt;li&gt;Focus: development and optimization&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Plan 2: Quick Fixes Needed&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Critical issues present&lt;/li&gt;
&lt;li&gt;Fix plan: 2-4 weeks (priority)&lt;/li&gt;
&lt;li&gt;Then quarterly improvement plan&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Plan 3: Stabilization Required&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiple critical issues&lt;/li&gt;
&lt;li&gt;Stabilization plan: 1-3 months&lt;/li&gt;
&lt;li&gt;Oversight in firefighting mode&lt;/li&gt;
&lt;li&gt;After stabilization - transition to development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Agreed action plan with priorities and timelines.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="phase-6-onboarding-ongoing"&gt;Phase 6: Onboarding (ongoing)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Integrate into team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Actions:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Join communications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slack/Teams channels&lt;/li&gt;
&lt;li&gt;Standups&lt;/li&gt;
&lt;li&gt;Retros&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set up regular touchpoints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Weekly sync with Tech Lead (30 min)&lt;/li&gt;
&lt;li&gt;Design review (on demand)&lt;/li&gt;
&lt;li&gt;ADR review (as created)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Define control points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code review of critical changes&lt;/li&gt;
&lt;li&gt;ADR approval&lt;/li&gt;
&lt;li&gt;Pre-release review&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Architect integrated into team.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="process-artifacts"&gt;Process Artifacts
&lt;/h2&gt;&lt;p&gt;Formalized the entire process as templates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I created:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Onboarding process&lt;/strong&gt; (6 phases)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each phase description&lt;/li&gt;
&lt;li&gt;Time frames&lt;/li&gt;
&lt;li&gt;Communication templates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Onboarding checklist&lt;/strong&gt; (11 sections, 80+ items)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Business context&lt;/li&gt;
&lt;li&gt;System analysis&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Code and tests&lt;/li&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audit template&lt;/strong&gt; (12 sections)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Report structure&lt;/li&gt;
&lt;li&gt;Evaluation criteria&lt;/li&gt;
&lt;li&gt;Recommendations format&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automated validation&lt;/strong&gt; (215 metrics)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Checklist verification&lt;/li&gt;
&lt;li&gt;Scoring (1-10)&lt;/li&gt;
&lt;li&gt;Automatic report&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Where to look:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Onboarding process: &lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;github.com/mshogin/archlint/templates/project-handover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;System audit: &lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;github.com/mshogin/archlint/templates/system-audit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="success-metrics"&gt;Success Metrics
&lt;/h2&gt;&lt;p&gt;How to know the process works?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Metric 1: Onboarding time&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &amp;lt; 2 weeks&lt;/li&gt;
&lt;li&gt;Measure: from initiation to onboarding&lt;/li&gt;
&lt;li&gt;Why important: quick oversight start&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Metric 2: Critical issues closure&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &amp;gt; 80% per quarter&lt;/li&gt;
&lt;li&gt;Measure: percent of closed P0 from report&lt;/li&gt;
&lt;li&gt;Why important: real quality impact&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Metric 3: Tech Lead satisfaction&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &amp;gt; 4/5&lt;/li&gt;
&lt;li&gt;Measure: survey after 3 months oversight&lt;/li&gt;
&lt;li&gt;Why important: team trust&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Metric 4: Design review participation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &amp;gt; 90%&lt;/li&gt;
&lt;li&gt;Measure: percent of reviews architect participated in&lt;/li&gt;
&lt;li&gt;Why important: process involvement&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="usage-example"&gt;Usage Example
&lt;/h2&gt;&lt;p&gt;Theory so far. Next week I start onboarding 4 projects - let&amp;rsquo;s see what breaks in reality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plan:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Week 1: Initiation + kickoff for all 4 projects&lt;/li&gt;
&lt;li&gt;Weeks 2-3: Information gathering and audit (parallel)&lt;/li&gt;
&lt;li&gt;Week 4: Decision + onboarding&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Will track:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where process got stuck&lt;/li&gt;
&lt;li&gt;Which checklist items were useless&lt;/li&gt;
&lt;li&gt;How long each phase took&lt;/li&gt;
&lt;li&gt;What problems weren&amp;rsquo;t detected&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After completion - will write second article with real experience and gotchas.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="summary"&gt;Summary
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;What&amp;rsquo;s done:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;6-phase onboarding process (7-14 days)&lt;/li&gt;
&lt;li&gt;Checklist (11 sections, 80+ items)&lt;/li&gt;
&lt;li&gt;Audit template (12 sections)&lt;/li&gt;
&lt;li&gt;Automated validation (215 metrics)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Systematic approach instead of chaos&lt;/li&gt;
&lt;li&gt;Reproducible process&lt;/li&gt;
&lt;li&gt;Control of critical aspects&lt;/li&gt;
&lt;li&gt;Measurable success metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What&amp;rsquo;s next:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Test on 4 projects&lt;/li&gt;
&lt;li&gt;Gather feedback&lt;/li&gt;
&lt;li&gt;Improve process&lt;/li&gt;
&lt;li&gt;Write second article with real experience&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;How do you onboard projects? And do you use AI for audits?&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="links"&gt;Links
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;Onboarding process&lt;/a&gt; - 6 phases, templates&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;System audit&lt;/a&gt; - checklists, validation&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/adr" target="_blank" rel="noopener"
&gt;ADR templates&lt;/a&gt; - Architecture Decision Records&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/specifications" target="_blank" rel="noopener"
&gt;Specifications&lt;/a&gt; - for new projects&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>AI Doesn't Replace - AI Changes the Role</title><link>https://mshogin.com/notes/ai-analyst-role-shift/</link><pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/ai-analyst-role-shift/</guid><description>&lt;p&gt;Recently stumbled upon a stat: &lt;a class="link" href="https://hrexecutive.com/the-ai-layoff-trap-why-half-will-be-quietly-rehired/" target="_blank" rel="noopener"
&gt;55% of companies&lt;/a&gt; that laid off people because of AI now regret it. And a &lt;a class="link" href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" target="_blank" rel="noopener"
&gt;METR study&lt;/a&gt; showed something weird - developers think they work 20% faster with AI, but actually turned out to be 19% slower.&lt;/p&gt;
&lt;p&gt;Then I read Hinton saying that in a couple years AI will do in minutes what takes an engineer a month. And &lt;a class="link" href="https://www.technologyreview.com/2025/12/15/1128352/rise-of-ai-coding-developers-2026/" target="_blank" rel="noopener"
&gt;AWS CEO&lt;/a&gt; responds calling the refusal to hire juniors &amp;ldquo;one of the dumbest things I&amp;rsquo;ve heard.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So who&amp;rsquo;s right?&lt;/p&gt;
&lt;p&gt;My experience says - both are wrong. AI doesn&amp;rsquo;t replace people. And it doesn&amp;rsquo;t slow work down. It just changes what we do.&lt;/p&gt;
&lt;h2 id="what-ive-given-to-ai"&gt;What I&amp;rsquo;ve Given to AI
&lt;/h2&gt;&lt;p&gt;Honestly - almost all analytics. Draft diagrams, text editing, searching and analyzing information. I&amp;rsquo;ve practically stopped coding by hand - always work with an agent now. Need some expertise - AI is my first stop.&lt;/p&gt;
&lt;p&gt;Sounds like I&amp;rsquo;ve given everything away. But no.&lt;/p&gt;
&lt;h2 id="what-i-wont-give-up"&gt;What I Won&amp;rsquo;t Give Up
&lt;/h2&gt;&lt;p&gt;Health. This is clear for me. I don&amp;rsquo;t mind if a doctor uses AI - actually, that&amp;rsquo;s good. But it should be a doctor. With education. With experience. AI as a tool - yes. AI instead of a doctor - no.&lt;/p&gt;
&lt;p&gt;Same with a psychologist. I like working with a real person, and I don&amp;rsquo;t see how that can be replaced. Same with a coach.&lt;/p&gt;
&lt;p&gt;Everything related to my health, consciousness, awareness - only to professionals. Who can use AI in their work, but professionals nonetheless.&lt;/p&gt;
&lt;h2 id="about-this-productivity-paradox"&gt;About This &amp;ldquo;Productivity Paradox&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;That METR study got me thinking. People think they&amp;rsquo;re faster, but actually slower. A paradox, they say.&lt;/p&gt;
&lt;p&gt;I disagree.&lt;/p&gt;
&lt;p&gt;How did it used to work? You could try one or two implementation options. Picked something, went ahead. Hit problems - made a third version. Then fourth. And it all piled up. First version lying around somewhere, second, third - and you&amp;rsquo;re already on the fifth, dragging legacy behind.&lt;/p&gt;
&lt;p&gt;Now I try a bunch of options at once in the same time. Yes, each specific option takes more time. But I&amp;rsquo;m not dragging three failed attempts behind me. I pick the best option before I start burying it in production.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s not slowing down. That&amp;rsquo;s a different way of working.&lt;/p&gt;
&lt;h2 id="juniors"&gt;Juniors
&lt;/h2&gt;&lt;p&gt;AWS CEO put it well: &amp;ldquo;How&amp;rsquo;s that going to work ten years from now when nobody&amp;rsquo;s learned anything?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Completely agree. There has to be knowledge transfer. Generational turnover of specialists.&lt;/p&gt;
&lt;p&gt;Yes, with AI you can make websites and telegram bots without much education. But the industry isn&amp;rsquo;t just websites and bots. There&amp;rsquo;s tons of stuff that needs higher math. That needs computer science. Juniors are needed. And they need to be trained.&lt;/p&gt;
&lt;h2 id="how-my-role-has-changed"&gt;How My Role Has Changed
&lt;/h2&gt;&lt;p&gt;Writing code by hand - no point anymore. Now I think about architecture. Design systems. Do reviews. Validate what came out.&lt;/p&gt;
&lt;p&gt;And the design itself is also with AI - you talk to the agent, break down the task. Then hand it off for implementation and check the result.&lt;/p&gt;
&lt;p&gt;Basically, the role has shifted. Before - executor. Now - designer and validator.&lt;/p&gt;
&lt;h2 id="whats-become-more-important"&gt;What&amp;rsquo;s Become More Important
&lt;/h2&gt;&lt;p&gt;Systematic approach. These stories about the &amp;ldquo;hero developer&amp;rdquo; who fixed everything at night, or the &amp;ldquo;firefighter&amp;rdquo; who&amp;rsquo;s everywhere at once - that&amp;rsquo;s going away. People who solve problems systematically are valued.&lt;/p&gt;
&lt;p&gt;And another skill has emerged: building your own system for working with AI. Just dictating a prompt - doesn&amp;rsquo;t work. You need an actual system. Your own prompts, rules, skills, agents.&lt;/p&gt;
&lt;p&gt;I spend time not just on work tasks, but on this system. It&amp;rsquo;s my asset. My intellectual property, if you will.&lt;/p&gt;
&lt;h2 id="whats-the-point"&gt;What&amp;rsquo;s the Point
&lt;/h2&gt;&lt;p&gt;AI doesn&amp;rsquo;t replace specialists. It changes what they do.&lt;/p&gt;
&lt;p&gt;55% of companies regret layoffs not because AI doesn&amp;rsquo;t work. But because they didn&amp;rsquo;t understand - people&amp;rsquo;s role has changed, not disappeared.&lt;/p&gt;
&lt;p&gt;Less execution, more design. Less heroics, more system. Less hand-coding, more work on your own tools.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s how it looks right now. At least for me.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;More on AI in development and architecture: &lt;a class="link" href="https://t.me/MikeShogin" target="_blank" rel="noopener"
&gt;Telegram&lt;/a&gt;&lt;/p&gt;</description></item><item><title>$HOME in Git: One Config for Claude Code</title><link>https://mshogin.com/notes/claude-config-consolidation/</link><pubDate>Fri, 09 Jan 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/claude-config-consolidation/</guid><description>&lt;p&gt;Multiple projects. Each with its own CLAUDE.md, its own rules. You improve something in one place - you want it elsewhere. Copy. Improve there. Copy back. Round and round.&lt;/p&gt;
&lt;p&gt;At some point I had a mess of different versions of the same rules scattered across a dozen projects. The copy-paste circus was annoying, but I kept putting it off.&lt;/p&gt;
&lt;p&gt;During the New Year holidays, I decided to fix it.&lt;/p&gt;
&lt;h2 id="the-solution"&gt;The Solution
&lt;/h2&gt;&lt;p&gt;Moved everything to my home directory &lt;code&gt;~/.claude/&lt;/code&gt;. One config for all projects.&lt;/p&gt;
&lt;p&gt;Yes, I&amp;rsquo;m now coupled to my home directory structure. But that structure hasn&amp;rsquo;t changed in years - &lt;code&gt;~/my/&lt;/code&gt; for projects, &lt;code&gt;~/education/&lt;/code&gt; for learning, &lt;code&gt;~/family/&lt;/code&gt; for family stuff. Risk is minimal.&lt;/p&gt;
&lt;h2 id="structure"&gt;Structure
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;~/.&lt;/span&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CLAUDE&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Core principles (task confirmation, formatting)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HOME_MAP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Home directory map for navigation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Rules (auto-loaded)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;architecture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Architecture principles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;coaching&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Coaching questions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dna&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Writing style&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;navigation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Context detection by keywords&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Project-specific rules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;aitrader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Rules for aitrader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Slash commands&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# /ms-todos - task list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# /ms-add-note - add note&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Skills&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Blog post writing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;review&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Go code review&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;social&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Social media content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Custom agents&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reviewer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="c1"&gt;# Go code reviewer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hooks&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Hooks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="c1"&gt;# Session logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="how-navigation-works"&gt;How Navigation Works
&lt;/h2&gt;&lt;p&gt;The key file is &lt;code&gt;HOME_MAP.md&lt;/code&gt;. It&amp;rsquo;s a map of the entire home directory with context detection rules.&lt;/p&gt;
&lt;p&gt;Claude sees keywords in your request and knows which directory to work in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aitrader&lt;/code&gt;, &lt;code&gt;archlint&lt;/code&gt;, &lt;code&gt;blog&lt;/code&gt; -&amp;gt; &lt;code&gt;~/my/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;course&lt;/code&gt;, &lt;code&gt;book&lt;/code&gt;, &lt;code&gt;learning&lt;/code&gt; -&amp;gt; &lt;code&gt;~/education/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory&lt;/code&gt;, &lt;code&gt;remember&lt;/code&gt;, &lt;code&gt;mission&lt;/code&gt; -&amp;gt; &lt;code&gt;~/my/org-roam/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If context is ambiguous - it asks.&lt;/p&gt;
&lt;h2 id="project-specific-rules"&gt;Project-Specific Rules
&lt;/h2&gt;&lt;p&gt;Need specific rules for a project? Add them to &lt;code&gt;rules/projects/&lt;/code&gt;. For example, &lt;code&gt;aitrader.md&lt;/code&gt; contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to run the collector (without proxy for Tinkoff API)&lt;/li&gt;
&lt;li&gt;Test commands&lt;/li&gt;
&lt;li&gt;Project specifics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These rules load globally but apply only when working in the aitrader context.&lt;/p&gt;
&lt;h2 id="git"&gt;Git
&lt;/h2&gt;&lt;p&gt;Everything under git. One repository, one history.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; is large - it excludes almost everything that shouldn&amp;rsquo;t be versioned: credentials, caches, Downloads, Documents, Library, .ssh. But everything else - configs, &lt;code&gt;.claude/&lt;/code&gt;, dotfiles - is tracked. Planning to add private repos as submodules, so one &lt;code&gt;git clone&lt;/code&gt; restores the entire home directory.&lt;/p&gt;
&lt;p&gt;No more copying between projects. Improve a rule once - it works everywhere.&lt;/p&gt;
&lt;h2 id="result"&gt;Result
&lt;/h2&gt;&lt;p&gt;Before: a dozen projects with scattered CLAUDE.md files, constant copying, different versions of the same thing.&lt;/p&gt;
&lt;p&gt;After: one &lt;code&gt;~/.claude/&lt;/code&gt;, structured rules, git for versioning. Improve once - works everywhere.&lt;/p&gt;
&lt;p&gt;Downside: tight coupling to home directory structure. For me it&amp;rsquo;s not a problem - the structure is stable.&lt;/p&gt;</description></item><item><title>Spec-driven development: Reproduce a project from specs alone</title><link>https://mshogin.com/notes/archlint-reproduction/</link><pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/archlint-reproduction/</guid><description>&lt;p&gt;Ran an experiment: can you reproduce a project if you give AI only specifications without source code?&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Original project: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;archlint&lt;/a&gt; - a Go architecture analysis tool&lt;/li&gt;
&lt;li&gt;Input: &lt;strong&gt;10 specifications&lt;/strong&gt; (Markdown + PlantUML), totaling &lt;strong&gt;73 KB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Claude Code received an empty directory and specs&lt;/li&gt;
&lt;li&gt;Executor: Claude Code, started in an &lt;strong&gt;empty directory&lt;/strong&gt; and implemented the project from scratch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Specs covered all the basics: module init, Makefile, data model, Go-analyzer, Cobra CLI, &lt;code&gt;collect&lt;/code&gt;/&lt;code&gt;trace&lt;/code&gt; commands, tracer library, tracelint, and integration tests.&lt;/p&gt;
&lt;h2 id="time"&gt;Time
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;~20 minutes&lt;/strong&gt; from empty directory to working project.&lt;/p&gt;
&lt;h2 id="results"&gt;Results
&lt;/h2&gt;&lt;p&gt;Final assessment of the cloned repository:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Structural identity: 100%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloning success: 85.5%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semantic equivalence: ~75%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mutations: 23&lt;/strong&gt; (3 critical, 8 medium, 12 minor)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interesting detail: the clone turned out &lt;strong&gt;shorter&lt;/strong&gt; than the original - 1,845 lines of Go vs 2,159 (-14.5%) with the same number of &lt;code&gt;.go&lt;/code&gt; files (13).&lt;/p&gt;
&lt;h2 id="mutations-that-actually-matter"&gt;Mutations that actually matter
&lt;/h2&gt;&lt;p&gt;Three &amp;ldquo;critical&amp;rdquo; mutations - exactly the places where the specification leaves room for interpretation (i.e., for creativity you didn&amp;rsquo;t order):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sequence diagram building:&lt;/strong&gt; changed the algorithm for forming calls in the diagram (logic for call stack and write conditions).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tracerlint:&lt;/strong&gt; clone considers deprecated &lt;code&gt;Exit()&lt;/code&gt; call acceptable, while the original does not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GoAnalyzer:&lt;/strong&gt; added &lt;code&gt;baseDir&lt;/code&gt; and &lt;code&gt;modulePath&lt;/code&gt; fields - AI &amp;ldquo;improved&amp;rdquo; the model because the specs didn&amp;rsquo;t explicitly define the analyzer&amp;rsquo;s responsibility boundary (what to store inside, what to compute outside).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="takeaway"&gt;Takeaway
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Spec-driven development works as a mechanism for reproducing the &amp;ldquo;functional core&amp;rdquo;.&lt;/strong&gt; 73 KB of specifications was enough to quickly restore structure and core functionality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Critical deviations occur where the specification describes &amp;ldquo;what should be&amp;rdquo; but doesn&amp;rsquo;t define &amp;ldquo;how to verify it&amp;rdquo;.&lt;/strong&gt; For such places you need:
&lt;ul&gt;
&lt;li&gt;precise rules (invariants),&lt;/li&gt;
&lt;li&gt;input/output examples,&lt;/li&gt;
&lt;li&gt;golden tests (byte-by-byte/structural comparison),&lt;/li&gt;
&lt;li&gt;prohibition on &amp;ldquo;model extension&amp;rdquo; without an explicit spec item.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In short: AI can clone a project from specs quickly. But if there&amp;rsquo;s a gap in the specs - it will definitely squeeze in some &amp;ldquo;engineering optimization&amp;rdquo;. Sometimes useful. In critical places - usually not.&lt;/p&gt;
&lt;p&gt;Clone repository: &lt;a class="link" href="https://github.com/mshogin/archlint-reproduction" target="_blank" rel="noopener"
&gt;mshogin/archlint-reproduction&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Spec-Driven Development: Controlling AI Code Generation</title><link>https://mshogin.com/blog/spec-driven-development/</link><pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/spec-driven-development/</guid><description>&lt;img src="https://mshogin.com/blog/spec-driven-development/cover.en.svg" alt="Featured image of post Spec-Driven Development: Controlling AI Code Generation" /&gt;&lt;h2 id="in-this-article"&gt;In this article
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#observations" &gt;Observations&lt;/a&gt;: the problem with large MRs and AI code generation&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#hypothesis" &gt;Hypothesis&lt;/a&gt;: specifications as a contract&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#method" &gt;Method&lt;/a&gt;: storage structure and specification sizes&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#the-role-of-ai" &gt;The Role of AI&lt;/a&gt;: editor and executor&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#results" &gt;Results&lt;/a&gt;: reproducibility experiment&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#limitations" &gt;Limitations&lt;/a&gt; and &lt;a class="link" href="#conclusions" &gt;Conclusions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="observations"&gt;Observations
&lt;/h2&gt;&lt;p&gt;4000 lines in a single MR. Three hours reviewing, 12 comments, fixes - another 800 lines. On the fourth attempt I closed the tab and realized: the problem isn&amp;rsquo;t the code, it&amp;rsquo;s that nobody knew what exactly needed to be written.&lt;/p&gt;
&lt;p&gt;If you work with large codebases, this situation is familiar. Large MRs are a symptom. When it&amp;rsquo;s unclear what exactly needs to be done, developers write more code than necessary. They add things just in case. Cover scenarios nobody asked for. The MR grows not because the task is big, but because the boundaries are fuzzy.&lt;/p&gt;
&lt;p&gt;Another cause is the illusion that it&amp;rsquo;s easier to do everything in one task than to decompose. It seems like splitting creates extra work. In practice, a monolithic 4000-line MR can&amp;rsquo;t be properly reviewed, and bugs slip through to production.&lt;/p&gt;
&lt;p&gt;I use AI daily. Claude Code is my main tool - it can be configured to use different models: Anthropic, DeepSeek, GPT family, local ones via Ollama. At some point I noticed a pattern: the more precisely I formulate the task, the better the result. Prompts became increasingly structured - simple instructions, then templates, then something resembling technical specifications.&lt;/p&gt;
&lt;p&gt;Where&amp;rsquo;s the problem? At first I thought I was too lazy to give AI detailed instructions. Then I decided the AI Agent wasn&amp;rsquo;t gathering enough context - needed RAG or something similar. Eventually I realized the problem is in both places: creating full instructions feels like overkill, and how to help the agent gather the right context - unclear.&lt;/p&gt;
&lt;p&gt;But the main thing - there&amp;rsquo;s nothing to verify. No artifact you can point to and say: this is what was specified, this is what was built.&lt;/p&gt;
&lt;h2 id="hypothesis"&gt;Hypothesis
&lt;/h2&gt;&lt;p&gt;The idea isn&amp;rsquo;t new - the industry has been talking about spec-first approach for a while. I wanted to try it for a long time and finally decided to test it.&lt;/p&gt;
&lt;p&gt;If requirements are formalized as a specification before coding begins, then:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;AI Agent will generate more predictable code&lt;/li&gt;
&lt;li&gt;Results can be validated against the specification&lt;/li&gt;
&lt;li&gt;Architecture will remain controllable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When AI Agent generates hundreds of lines of code per minute, the only way to control the result is to have a formal description of what should be produced, and a tool that verifies the implementation matches the specification. More on the latter in a separate article.&lt;/p&gt;
&lt;h2 id="method"&gt;Method
&lt;/h2&gt;&lt;p&gt;I decided to test the hypothesis on a real project - a tool for building architectural graphs from Go code. The rule was simple: not a single line of code without a specification.&lt;/p&gt;
&lt;p&gt;First specification - &lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/specs/done/0001-init-project.md" target="_blank" rel="noopener"
&gt;create an empty project&lt;/a&gt; with standard Go layout. Second - &lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/specs/done/0003-data-model.md" target="_blank" rel="noopener"
&gt;graph model&lt;/a&gt;. Third - &lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/specs/done/0004-go-analyzer.md" target="_blank" rel="noopener"
&gt;Go code analyzer&lt;/a&gt;. Over several days, 10 completed specifications accumulated.&lt;/p&gt;
&lt;h3 id="storage-structure"&gt;Storage Structure
&lt;/h3&gt;&lt;p&gt;Kanban-like organization via file system:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;specs/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── todo/ # task queue
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── 0010-feature-x.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── 0020-feature-y.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── inprogress/ # in progress (maximum one - WIP limit)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── 0005-current.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── done/ # completed
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 0001-init-project.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 0003-data-model.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 0004-go-analyzer.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Prioritization via numeric prefix: lower number - higher priority. State transitions - moving files between directories.&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph LR
TODO["todo/"] --&gt; INPROGRESS["inprogress/"]
INPROGRESS --&gt; DONE["done/"]
&lt;/div&gt;
&lt;h3 id="specification-sizes"&gt;Specification Sizes
&lt;/h3&gt;&lt;p&gt;Classification by time to write the specification (T-shirt sizing):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;S (Small)&lt;/strong&gt; - up to 10 minutes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M (Medium)&lt;/strong&gt; - 10-20 minutes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L (Large)&lt;/strong&gt; - more than 20 minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Size determines depth of elaboration. S-task: Problem Statement and 5 Acceptance Criteria. L-task: full UML/C4 diagrams, detailed Requirements, 15+ acceptance criteria. Correlation between specification size and result predictability is direct.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re starting from scratch - try an S-specification first. Minimal investment for the experiment.&lt;/p&gt;
&lt;h3 id="s-specification-example-project-initialization"&gt;S-Specification Example: Project Initialization
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Spec 0001: Initialize Standard Golang Project Layout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**Metadata:**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Priority: 0001
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Status: Done
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Effort: S
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Overview
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Problem Statement
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Need to create basic Go project structure for the archlint tool
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;according to standard development practices.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Solution Summary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Initialize Go module and create minimal project structure.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Requirements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R1: Go Module Initialization
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Initialize Go module with name github.com/mshogin/archlint
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R2: Minimal Directory Structure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Create cmd/archlint/ for entry point
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Create internal/ for private code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Create pkg/ for public libraries
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Acceptance Criteria
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC1: go.mod created with module path github.com/mshogin/archlint
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC2: cmd/archlint/main.go exists and compiles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC3: Directories internal/ and pkg/ exist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Minimum details, maximum specificity. AI gets clear task boundaries.&lt;/p&gt;
&lt;h3 id="m-specification-example-collect-command"&gt;M-Specification Example: Collect Command
&lt;/h3&gt;&lt;p&gt;Medium tasks require diagrams. I experimented with Sequence diagrams - sending them to the agent along with requirements. Noticed that with them the AI Agent produces roughly what&amp;rsquo;s expected.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Spec 0006: Implement Collect Command
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**Metadata:**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Priority: 0006
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Status: Done
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Effort: M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Overview
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Problem Statement
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Need to implement the collect command for gathering architecture
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from source code and saving the graph to a YAML file.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Solution Summary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Create a collect subcommand that uses GoAnalyzer to analyze code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;and saves the result in YAML format.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Architecture
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Sequence Flow (PlantUML)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;title Sequence: Collect Command
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;actor User
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;collectCmd&amp;#34; as CC
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;GoAnalyzer&amp;#34; as GA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;saveGraph&amp;#34; as SG
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;User -&amp;gt; CC: archlint collect . -o arch.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CC -&amp;gt; GA: Analyze(dir)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GA --&amp;gt; CC: *Graph
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CC -&amp;gt; SG: saveGraph(graph)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SG --&amp;gt; CC: nil
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CC --&amp;gt; User: &amp;#34;Graph saved to arch.yaml&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Requirements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R1: Command Definition
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;var collectCmd = &amp;amp;cobra.Command{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Use: &amp;#34;collect [directory]&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Short: &amp;#34;Collect architecture from source code&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Args: cobra.ExactArgs(1),
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; RunE: runCollect,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R2: Flags
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;-o, --output: output YAML file (default: architecture.yaml)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-l, --language: programming language (default: go)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Acceptance Criteria
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC1: Command accepts directory as argument
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC2: Flags -o and -l work
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC3: Result saved to YAML
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC4: Statistics printed for components
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Sequence diagram defines call order. AI follows it literally.&lt;/p&gt;
&lt;h3 id="l-specification-example-go-code-analyzer"&gt;L-Specification Example: Go Code Analyzer
&lt;/h3&gt;&lt;p&gt;Large tasks require multiple diagrams - Data Model and Sequence:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Spec 0004: Implement Go Code Analyzer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**Metadata:**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Priority: 0004
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Status: Done
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Effort: L
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Overview
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Problem Statement
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Need to implement a Go code analyzer that parses source code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;using AST and builds a dependency graph between components.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Solution Summary
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;Create GoAnalyzer in internal/analyzer package that uses
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go/ast and go/parser to analyze Go files and build the graph.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Architecture
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Data Model
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class GoAnalyzer {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -packages: map[string]*PackageInfo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -types: map[string]*TypeInfo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -functions: map[string]*FunctionInfo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -nodes: []model.Node
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -edges: []model.Edge
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +NewGoAnalyzer() *GoAnalyzer
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Analyze(dir string) (*model.Graph, error)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -parseFile(filename string) error
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -buildGraph()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class PackageInfo {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Name: string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Path: string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Imports: []string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class TypeInfo {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Name: string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Package: string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Kind: string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +Fields: []FieldInfo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GoAnalyzer &amp;#34;1&amp;#34; *-- &amp;#34;*&amp;#34; PackageInfo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GoAnalyzer &amp;#34;1&amp;#34; *-- &amp;#34;*&amp;#34; TypeInfo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Sequence Diagram
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;title Sequence: Code Analysis
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;actor User
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;GoAnalyzer&amp;#34; as GA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;go/parser&amp;#34; as GP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;participant &amp;#34;buildGraph&amp;#34; as BG
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;User -&amp;gt; GA: Analyze(dir)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;loop For each .go file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GA -&amp;gt; GP: ParseFile(filename)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GP --&amp;gt; GA: *ast.File
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GA -&amp;gt; GA: Extract packages, types, functions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;end
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GA -&amp;gt; BG: buildGraph()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BG --&amp;gt; GA: *Graph
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GA --&amp;gt; User: *Graph, nil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Requirements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R1: AST Parsing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Parse all .go files in directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Extract packages, types, functions, methods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R2: Graph Building
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Create Node for each component
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Create Edge for each relationship (import, calls, uses)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### R3: External Dependencies
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;-&lt;/span&gt; Identify external dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Mark them as entity: external
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Acceptance Criteria
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;&lt;/span&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC1: Analyzer correctly parses Go code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC2: All component types extracted
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC3: All relationship types identified
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC4: External dependencies identified
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;- [x]&lt;/span&gt; AC5: Graph serializes to YAML
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For L-tasks multiple diagrams are a necessity. Data Model, Sequence, Component - together they define application architecture and manage dependencies between components.&lt;/p&gt;
&lt;h2 id="the-role-of-ai"&gt;The Role of AI
&lt;/h2&gt;&lt;p&gt;AI accelerates the work, but I don&amp;rsquo;t delegate architecture: decisions are fixed in the specification, go through review, and are verified by validators. However, decisions rarely come from thin air: I bring initial options and constraints, the agent suggests alternatives and highlights blind spots. This affects my thinking, and I&amp;rsquo;m aware of it. The final yes/no and responsibility are mine.&lt;/p&gt;
&lt;p&gt;The agent has two areas of responsibility.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Specification Editor&lt;/strong&gt;
I dictate a raw stream of thoughts by voice (I dictate faster than I type). The agent formats it according to &lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/templates/spec-template.md" target="_blank" rel="noopener"
&gt;my specification template&lt;/a&gt;: organizes into sections, clarifies the unsaid, formulates requirements and acceptance criteria so they can be verified. After that I review and fix the specification as the source contract.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementation Executor&lt;/strong&gt;
When the specification is agreed upon, I hand it to the agent for implementation. The agent writes code according to the specification, and I verify the result: review, validation, iterations until the architecture becomes clean and predictable.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="mermaid"&gt;
graph LR
A["Ideas/options (me)"] --&gt; B["AI supplements and formalizes"]
B --&gt; C["Specification"]
C --&gt; D["Review and decisions (me)"]
D --&gt; E["Implementation (AI)"]
&lt;/div&gt;
&lt;h2 id="results"&gt;Results
&lt;/h2&gt;&lt;p&gt;Over several days - 10 completed specifications and a working project. Code matches the architecture from diagrams.&lt;/p&gt;
&lt;p&gt;To test whether specifications are self-sufficient, I ran an experiment: gave Claude Code an empty directory and 10 specifications from archlint - no access to source code. The task: recreate the project from scratch.&lt;/p&gt;
&lt;p&gt;Result in 20 minutes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;85.5%&lt;/strong&gt; reproduction success rate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100%&lt;/strong&gt; structural identity (directories, files, types)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;23 mutations&lt;/strong&gt; in implementation details&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Project structure reproduced completely. All acceptance criteria from specifications met. Project compiles and passes tests.&lt;/p&gt;
&lt;p&gt;Mutations occurred where specifications described what to do, but not how. Critical example: the sequence diagram building algorithm was implemented differently - functionally equivalent, but with different call stack traversal logic. Another category of mutations - stylistic: comment language, function order in files, variable naming.&lt;/p&gt;
&lt;p&gt;Takeaway for improving specifications: critical algorithms need pseudocode or concrete input/output examples. A specification with what + how yields more precise reproduction than what alone.&lt;/p&gt;
&lt;p&gt;Full report with mutation catalog: &lt;a class="link" href="https://github.com/mshogin/archlint-reproduction" target="_blank" rel="noopener"
&gt;github.com/mshogin/archlint-reproduction&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="specification-idempotency"&gt;Specification Idempotency
&lt;/h2&gt;&lt;p&gt;For specifications to remain reproducible, all changes must go through them. No tweaks in copilot mode, no chats with &amp;ldquo;fix this thing&amp;rdquo;. Every change - update the specification, then implement.&lt;/p&gt;
&lt;p&gt;This is the main challenge. You want to quickly fix a bug in dialogue rather than go back to the spec. But every such fix - loss of reproducibility.&lt;/p&gt;
&lt;p&gt;The trade-off is obvious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Need results here and now - copilot mode is faster&lt;/li&gt;
&lt;li&gt;Need reproducibility - only through specifications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The choice depends on context. Prototype or experiment - copilot. Production code with a long lifecycle - specifications.&lt;/p&gt;
&lt;h2 id="limitations"&gt;Limitations
&lt;/h2&gt;&lt;p&gt;The approach doesn&amp;rsquo;t solve problems automatically. It doesn&amp;rsquo;t replace domain understanding, doesn&amp;rsquo;t invent requirements, and doesn&amp;rsquo;t guarantee good design. It makes errors visible earlier and forces architecture to stay within bounds.&lt;/p&gt;
&lt;p&gt;The cost: time for writing specifications, reviewing them, and iterations after validation. If you treat specs formally, everything slides back into chaos. Honestly ask yourself: are you willing to spend 10-30 minutes on a specification so the agent can implement it in 5-20 minutes?&lt;/p&gt;
&lt;p&gt;Implementation details vary. The reproducibility experiment showed 23 mutations - algorithms are interpreted differently, code style differs. Critical sections need pseudocode, not just descriptions.&lt;/p&gt;
&lt;p&gt;I think the approach works well where there&amp;rsquo;s an established, formed, and working process. Processes focused on discipline, clear areas of responsibility, review, definition of done. You can think of this process as a conveyor delivering software 24/7.&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions
&lt;/h2&gt;&lt;p&gt;The hypothesis was confirmed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;AI generates more predictable code - yes, with diagrams present&lt;/li&gt;
&lt;li&gt;Results can be validated - yes, 85.5% reproducibility&lt;/li&gt;
&lt;li&gt;Architecture remains controllable - yes, 100% structural identity&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The essence is simple: without specification there&amp;rsquo;s nothing to verify, with specification - there&amp;rsquo;s an artifact for validation. No need for perfect AI or perfect prompt.&lt;/p&gt;
&lt;p&gt;The experiment continues.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Templates and examples:&lt;/strong&gt; &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;github.com/mshogin/archlint&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re trying the spec-driven approach or already using it - share in the comments what works and what doesn&amp;rsquo;t. I write about AI code generation and architecture practices on Telegram: &lt;a class="link" href="https://t.me/MikeShogin" target="_blank" rel="noopener"
&gt;@MikeShogin&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Structural and Behavioral Architecture: Graph-Based Approach to Complexity Control</title><link>https://mshogin.com/blog/architecture-graphs/</link><pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/architecture-graphs/</guid><description>&lt;img src="https://mshogin.com/blog/architecture-graphs/cover.en.svg" alt="Featured image of post Structural and Behavioral Architecture: Graph-Based Approach to Complexity Control" /&gt;&lt;h2 id="why-vibe-coding-doesnt-work"&gt;Why Vibe Coding Doesn&amp;rsquo;t Work
&lt;/h2&gt;&lt;p&gt;With the emergence of AI agents, software development has changed dramatically. Like many developers, I started actively using Claude, Cursor, and other tools to automate code writing. The results were initially impressive: in one evening, doing system analysis, architecture design, and prompt engineering, I could generate up to 100,000 lines of code.&lt;/p&gt;
&lt;p&gt;The process was engaging. There was no need to manually write implementations - just describe requirements, discuss architectural vision with AI, clarify details, and code would appear. I could work on my pet projects in the evenings, talking with artificial intelligence like a colleague. This was true vibe coding - a pleasant, creative process unburdened by routine.&lt;/p&gt;
&lt;p&gt;Problems didn&amp;rsquo;t start immediately. The first few days went smoothly: AI quickly generated code, tests passed, functionality worked. But then, after about a week or two of active development, I began noticing alarming symptoms.&lt;/p&gt;
&lt;h3 id="symptoms-of-codebase-degradation"&gt;Symptoms of Codebase Degradation
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Agents started slowing down.&lt;/strong&gt; What used to take minutes now required tens of minutes. AI began looping on simple tasks, generating excessive code, suggesting refactoring almost the entire project to fix a small bug. The context grew too large, and the agent got lost in its own code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Architectural anti-patterns appeared.&lt;/strong&gt; The last straw was when reviewing code I discovered this construction:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// in the main function&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;intermediate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// inside calls processData(input)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intermediate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// inside calls processData(input) again!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// func transform(input) {&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// tmp := processData(input)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// result := combine(input)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// return reuslt * 2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// func combine(intermediate) {&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// result := processData(input) // same function, same arguments!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// return intermediate + result&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;processData&lt;/code&gt; function was called twice with identical arguments, but this duplication was hidden inside &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;combine&lt;/code&gt;. AI didn&amp;rsquo;t track that the result could be reused and generated similar code in different functions. But this was just the tip of the iceberg.&lt;/p&gt;
&lt;p&gt;Digging deeper, I found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functions with 15-20 parameters, half of which were passed straight through&lt;/li&gt;
&lt;li&gt;Circular dependencies between packages hidden through interfaces&lt;/li&gt;
&lt;li&gt;Duplication of business logic in three different places with slight variations&lt;/li&gt;
&lt;li&gt;God objects that knew about the entire system&lt;/li&gt;
&lt;li&gt;Layers of abstractions that abstracted nothing but only complicated the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Code became unmaintainable.&lt;/strong&gt; After two weeks, the project turned into what&amp;rsquo;s hard to call anything other than a mess. Adding new functionality required more and more time. AI proposed solutions that worked but further tangled the architecture. Every change pulled a chain of other changes in unexpected places.&lt;/p&gt;
&lt;p&gt;I got tired of creating projects that live two weeks and then become legacy. These were my own pet projects that I did for fun. I&amp;rsquo;m not even talking about production systems - that&amp;rsquo;s completely unacceptable there. I wanted to do development and product growth, not archaeological digs in my own code.&lt;/p&gt;
&lt;h3 id="stop-and-understand"&gt;Stop and Understand
&lt;/h3&gt;&lt;p&gt;I made a decision: stop generating new projects doomed to become unmaintainable and systematically understand the problem. Shifted focus from code generation to research work.&lt;/p&gt;
&lt;p&gt;The main research question: &lt;strong&gt;how to develop projects with AI agents so they remain evolvable and maintainable?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After analyzing the problem, I came to a key conclusion: vibe coding without formal architecture control is a dead end. AI agents excellently generate code that works here and now. But they don&amp;rsquo;t see the big picture of architecture, don&amp;rsquo;t track accumulation of technical debt, don&amp;rsquo;t notice emerging anti-patterns.&lt;/p&gt;
&lt;p&gt;An engineering approach is needed: formal architecture description, automatic validation, quality metrics. Architecture must be explicit, verifiable, controlled. Only this way can codebase degradation be prevented.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m starting a series of articles on architecture control research, viewing it as a graph data structure. In this first article, I&amp;rsquo;ll show how to automatically build two types of architectural graphs: structural (static) and behavioral (dynamic). All examples are based on a real project &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;archlint&lt;/a&gt; - a tool for automatic construction and validation of architectural graphs that I&amp;rsquo;m developing during the research.&lt;/p&gt;
&lt;p&gt;In subsequent articles of the series, I&amp;rsquo;ll cover validation of architectural rules and code quality metrics based on graph theory.&lt;/p&gt;
&lt;h2 id="structural-architecture-static-system-graph"&gt;Structural Architecture: Static System Graph
&lt;/h2&gt;&lt;p&gt;When we talk about software system architecture, we often mean its structure: what components the system consists of, how they&amp;rsquo;re organized, how they&amp;rsquo;re connected to each other. Structural architecture is a static picture capturing potential connections between code elements.&lt;/p&gt;
&lt;h3 id="why-a-formal-structure-model-is-needed"&gt;Why a Formal Structure Model is Needed
&lt;/h3&gt;&lt;p&gt;In traditional development, structural architecture exists as diagrams in documentation, team conventions, knowledge in experienced developers&amp;rsquo; heads. This suffices when code is written by people who understand context and keep the big picture in mind.&lt;/p&gt;
&lt;p&gt;With AI agents, the situation is different. An agent works in limited context, has no global system vision, doesn&amp;rsquo;t remember architectural decisions made a week ago. Each time generating code, it sees only a fragment of the system in the context window.&lt;/p&gt;
&lt;p&gt;The result is predictable: architecture degrades. Circular dependencies appear, code duplication, layered structure breaks. Informal conventions don&amp;rsquo;t work - there&amp;rsquo;s no one to follow them.&lt;/p&gt;
&lt;p&gt;Formal solution: make architecture explicit, automatically verifiable. A mathematical model is needed that accurately describes system structure and allows automatic validation of its correctness.&lt;/p&gt;
&lt;h3 id="graph-as-a-formal-model"&gt;Graph as a Formal Model
&lt;/h3&gt;&lt;p&gt;Structural architecture can be represented through a mathematical abstraction - a directed graph G = (V, E), where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;V (vertices)&lt;/strong&gt; - set of nodes representing system components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E (edges)&lt;/strong&gt; - set of edges representing connections between components&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each node v ∈ V has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt; - unique identifier (e.g., full package or function name)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;type&lt;/strong&gt; - component type (package, struct, function, method, interface)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;properties&lt;/strong&gt; - additional properties (filename, code line, visibility)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each edge e ∈ E has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;from&lt;/strong&gt; - source node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;to&lt;/strong&gt; - target node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;type&lt;/strong&gt; - connection semantics (contains, calls, uses, imports, embeds)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This simple model turns out powerful enough to describe real systems. The graph allows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visualizing&lt;/strong&gt; architecture at different abstraction levels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validating&lt;/strong&gt; architectural rules (e.g., &amp;ldquo;UI layer must not depend on DB layer&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Computing metrics&lt;/strong&gt; (connectivity, cyclomatic complexity, dependency depth)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tracking changes&lt;/strong&gt; over time&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="real-example-archlint-architecture"&gt;Real Example: archlint Architecture
&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s examine the structural architecture of a real project - archlint. This is a tool for building and analyzing architectural graphs, written in Go. Let&amp;rsquo;s see how its structure looks as a graph.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Package Level (8 packages):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd/archlint - main binary for architecture collection
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd/tracelint - linter for checking tracing coverage
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;internal/analyzer - Go source code analysis via AST
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;internal/model - architecture graph model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;internal/cli - CLI commands implementation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;internal/linter - tracing correctness validation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pkg/tracer - execution tracing library
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tests/testdata/sample - test examples with instrumentation
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Organization in &lt;code&gt;internal/&lt;/code&gt; vs &lt;code&gt;pkg/&lt;/code&gt; follows standard Go conventions: &lt;code&gt;internal&lt;/code&gt; contains private packages used only inside the project, &lt;code&gt;pkg&lt;/code&gt; - public libraries that other projects can use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Types:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Data types are organized by domains:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Graph model&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;architectural&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;representation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Edge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;edge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;between&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Source code analyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GoAnalyzer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PackageInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TypeInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;information&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MethodInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FieldInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CallInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Execution tracing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Trace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;execution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;individual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;execution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SequenceDiagram&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;diagram&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SequenceCall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;diagram&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UMLConfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;generation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Functionality is distributed across packages according to single responsibility principle. For example, in &lt;code&gt;internal/cli&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Execute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CLI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saveGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saveContexts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;contexts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;printContextsInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;contexts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runTrace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Connections Between Components:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The connection graph shows dependencies between packages and data types:&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph TB
cmdArchlint[cmd/archlint&lt;br/&gt;main binary]
cmdTracelint[cmd/tracelint&lt;br/&gt;linter binary]
analyzer[internal/analyzer&lt;br/&gt;code analysis]
model[internal/model&lt;br/&gt;graph model]
cli[internal/cli&lt;br/&gt;CLI commands]
linter[internal/linter&lt;br/&gt;trace validation]
tracer[pkg/tracer&lt;br/&gt;tracing library]
cmdArchlint --&gt;|uses| cli
cmdTracelint --&gt;|uses| linter
cli --&gt;|uses| analyzer
cli --&gt;|uses| tracer
analyzer --&gt;|produces| model
tracer --&gt;|uses| model
linter --&gt;|uses| tracer
style cmdArchlint fill:#e1f5ff
style cmdTracelint fill:#e1f5ff
style analyzer fill:#fff4e1
style model fill:#f0f0f0
style tracer fill:#d4edda
&lt;/div&gt;
&lt;p&gt;This diagram shows high-level architecture. We can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two binaries (&lt;code&gt;cmd/archlint&lt;/code&gt; and &lt;code&gt;cmd/tracelint&lt;/code&gt;) use different subsystems&lt;/li&gt;
&lt;li&gt;The analyzer doesn&amp;rsquo;t depend on CLI, can be used independently&lt;/li&gt;
&lt;li&gt;The graph model (&lt;code&gt;internal/model&lt;/code&gt;) is the central data structure&lt;/li&gt;
&lt;li&gt;Tracer is a public library (&lt;code&gt;pkg/tracer&lt;/code&gt;) that other projects can use&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="automatic-graph-building-from-source-code"&gt;Automatic Graph Building from Source Code
&lt;/h3&gt;&lt;p&gt;Theoretical model is good, but automation is needed. Manually describing a graph of hundreds of components and connections is unrealistic. Moreover, the graph must automatically update with every code change.&lt;/p&gt;
&lt;p&gt;Building the structural graph happens in four stages:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 1: Source Code Analysis&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using the standard &lt;code&gt;go/ast&lt;/code&gt; package, we go through all project files and build an abstract syntax tree (AST). AST gives complete information about code structure: packages, imports, types, functions, methods, calls.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ archlint collect . -o architecture.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The command recursively analyzes all &lt;code&gt;.go&lt;/code&gt; files in the current directory and its subdirectories.&lt;/p&gt;
&lt;p&gt;Analysis result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Analyzing code: . (language: go)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Found components: 134
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - package: 8 # top-level packages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - struct: 18 # data structures
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - type: 1 # type aliases
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - function: 55 # regular functions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - method: 28 # struct methods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - external: 24 # external dependencies
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Found links: 189
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Important point: external dependencies are also accounted for. These are packages from Go standard library and third-party modules used by the project. The complete dependency picture includes them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 2: Graph Node Formation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Each found component becomes a graph node. Nodes have a hierarchical identifier structure:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;analyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;package&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.GoAnalyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;GoAnalyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;struct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.GoAnalyzer.Analyze&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Analyze&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;method&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The identifier follows Go conventions: &lt;code&gt;package.Type.Method&lt;/code&gt;. This allows unambiguous identification of any system component.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stage 3: Graph Edge Formation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We create edges expressing connection semantics between components:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Package contains type&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.GoAnalyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;contains&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Type contains method&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.GoAnalyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.GoAnalyzer.Analyze&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;contains&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Function calls another function&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/cli.Execute&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/analyzer.NewGoAnalyzer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;calls&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Package imports another package&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cmd/archlint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;internal/cli&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;imports&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Different edge types allow distinguishing connection semantics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;contains&lt;/code&gt; - ownership relationship (package contains type, type contains method)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;calls&lt;/code&gt; - function or method call&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uses&lt;/code&gt; - type usage (e.g., in function signature or struct field)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;imports&lt;/code&gt; - package import&lt;/li&gt;
&lt;li&gt;&lt;code&gt;embeds&lt;/code&gt; - type embedding (embedding in Go)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Stage 4: Saving in YAML Format&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The output is a complete system graph in YAML format. This file can be:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Visualized:&lt;/strong&gt; Generate diagrams using PlantUML, Graphviz, or web interfaces like DocHub.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validated:&lt;/strong&gt; Check architectural rules. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Package &lt;code&gt;internal/model&lt;/code&gt; must not depend on anything except standard library&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Circular dependencies between packages are forbidden&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Maximum call nesting depth is 5 levels&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Analyzed:&lt;/strong&gt; Compute metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Graph connectivity (how many components are connected)&lt;/li&gt;
&lt;li&gt;Cyclomatic complexity&lt;/li&gt;
&lt;li&gt;Dependency tree depth&lt;/li&gt;
&lt;li&gt;Coupling and cohesion metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Track changes:&lt;/strong&gt; Compare graph versions, see architecture evolution over time.&lt;/p&gt;
&lt;p&gt;The structural graph of archlint is a complete, formal description of the system&amp;rsquo;s static structure that automatically updates and can be checked with every commit.&lt;/p&gt;
&lt;h2 id="behavioral-architecture-dynamic-execution-graph"&gt;Behavioral Architecture: Dynamic Execution Graph
&lt;/h2&gt;&lt;p&gt;Structural architecture shows what the system can do - all potential execution paths. But it doesn&amp;rsquo;t answer the question: what does the system actually do? Which components are used in specific scenarios? How does data flow through the system?&lt;/p&gt;
&lt;p&gt;To answer these questions, behavioral architecture is needed - a dynamic picture of system execution.&lt;/p&gt;
&lt;h3 id="why-behavioral-architecture-is-needed"&gt;Why Behavioral Architecture is Needed
&lt;/h3&gt;&lt;p&gt;Imagine a large system with a structural graph of thousands of components. You&amp;rsquo;re adding a new feature. Which components are actually used? What execution paths does a request take?&lt;/p&gt;
&lt;p&gt;Without behavioral architecture, you can only guess by reading code. With it - you see the exact sequence of calls built from actual execution.&lt;/p&gt;
&lt;p&gt;Behavioral architecture is critically important for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Understanding complex scenarios&lt;/strong&gt; - seeing the sequence of actions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance optimization&lt;/strong&gt; - finding bottlenecks in real execution paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identifying dead code&lt;/strong&gt; - functions that aren&amp;rsquo;t called in any scenario&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt; - automatic sequence diagrams instead of manual drawing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coverage control&lt;/strong&gt; - which business scenarios are covered by acceptance tests&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="how-acceptance-tests-form-behavioral-architecture"&gt;How Acceptance Tests Form Behavioral Architecture
&lt;/h3&gt;&lt;p&gt;Key idea: behavioral architecture isn&amp;rsquo;t invented abstractly - it&amp;rsquo;s extracted from real executable code. The source is acceptance tests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &amp;ldquo;one task - one acceptance test&amp;rdquo; principle:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With proper work decomposition, each task has an acceptance test that verifies implementation correctness. An acceptance test describes a specific system usage scenario - it defines an &lt;strong&gt;execution context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Task &amp;ldquo;Calculator with Memory&amp;rdquo; -&amp;gt; acceptance test &lt;code&gt;TestCalculateWithMemory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Task &amp;ldquo;Export Report to PDF&amp;rdquo; -&amp;gt; acceptance test &lt;code&gt;TestExportReportToPDF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Task &amp;ldquo;OAuth Authorization&amp;rdquo; -&amp;gt; acceptance test &lt;code&gt;TestOAuthLogin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each such test defines a separate context - an isolated system usage scenario.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Behavioral graph building process:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart LR
feature[Feature:&lt;br/&gt;Calculate with Memory]
test[Acceptance Test:&lt;br/&gt;TestCalculateWithMemory]
trace[Trace File:&lt;br/&gt;test_calculate.json]
seq[Sequence Diagram:&lt;br/&gt;PlantUML]
behgraph[Behavioral Graph:&lt;br/&gt;Numbered Edges]
context[Context:&lt;br/&gt;CalculateWithMemory]
feature --&gt; test
test --&gt; trace
trace --&gt; seq
trace --&gt; behgraph
seq --&gt; context
behgraph --&gt; context
style feature fill:#e1f5ff
style test fill:#fff4e1
style trace fill:#f0f0f0
style context fill:#d4edda
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Feature&lt;/strong&gt; - business requirement or task&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acceptance test&lt;/strong&gt; - code verifying the feature&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace&lt;/strong&gt; - complete call sequence during test execution&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sequence diagram&lt;/strong&gt; - visualization of interaction sequence&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Behavioral graph&lt;/strong&gt; - graph with numbered edges&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context&lt;/strong&gt; - formalized feature execution context&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="real-example-calculate-with-trace-context"&gt;Real Example: &amp;ldquo;Calculate With Trace&amp;rdquo; Context
&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s examine a real acceptance test from the archlint project:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TestCalculateWithTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Create directory for traces&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;traceDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;traces&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MkdirAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;traceDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mo"&gt;0755&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Start tracing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;TestCalculateWithTrace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StopTrace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;traceDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;test_calculate.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Execute acceptance test scenario&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;calc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;NewCalculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// create calculator&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// calculate (5 + 3) * 2 = 16&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Check acceptance criterion&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Expected 16, got %d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The test looks like a regular Go test but with tracing added. &lt;code&gt;tracer.StartTrace&lt;/code&gt; and &lt;code&gt;tracer.StopTrace&lt;/code&gt; wrap scenario execution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code Instrumentation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All system functions contain instrumentation points:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;NewCalculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.NewCalculator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.NewCalculator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Calculator.Calculate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Calculator.Calculate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// trace will record the call&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// trace will record the call&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddToMemory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// trace will record the call&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMemory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// trace will record the call&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Multiply&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExitSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sample.Multiply&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Instrumentation is minimal: &lt;code&gt;tracer.Enter&lt;/code&gt; at function start, &lt;code&gt;tracer.ExitSuccess&lt;/code&gt; at end (via defer). This doesn&amp;rsquo;t affect logic, only records the fact of the call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tracing Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After test execution, we get a JSON file with the complete sequence of all calls:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;test_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;TestCalculateWithTrace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;start_time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550942+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;end_time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550946+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;calls&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.NewCalculator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550942+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;exit_success&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.NewCalculator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550942+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.Calculator.Calculate&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550942+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.Add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550943+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;exit_success&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.Add&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550943+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;enter&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;function&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sample.Multiply&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2025-12-07T21:33:05.550943+03:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;depth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Each event contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;event&lt;/code&gt; - event type (enter/exit_success/exit_error)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;function&lt;/code&gt; - full function name&lt;/li&gt;
&lt;li&gt;&lt;code&gt;timestamp&lt;/code&gt; - exact call time&lt;/li&gt;
&lt;li&gt;&lt;code&gt;depth&lt;/code&gt; - nesting level (0 = top-level, 1 = first call, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;depth&lt;/code&gt; field allows reconstructing the call hierarchy: which function was called from which.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automatic Context Generation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A context is automatically generated from the trace file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ archlint trace ./traces -o contexts.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Result - formal context description in YAML:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;contexts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tests.testcalculatewithtrace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Calculate With Trace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Tests/Calculate With Trace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;plantuml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.new_calculator&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.calculator.calculate&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.add&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.multiply&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.calculator.add_to_memory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sample.calculator.get_memory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;output/traces/test_calculate.puml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The context includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;title&lt;/strong&gt; - human-readable name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;location&lt;/strong&gt; - place in context hierarchy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;components&lt;/strong&gt; - list of all components participating in the scenario&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uml.file&lt;/strong&gt; - path to automatically generated PlantUML diagram&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="visualizations-sequence-diagram-and-graph"&gt;Visualizations: Sequence Diagram and Graph
&lt;/h3&gt;&lt;p&gt;From one trace, two different representations can be obtained: a sequence diagram and a behavioral graph.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sequence diagram&lt;/strong&gt; shows the sequence of interactions between components over time:&lt;/p&gt;
&lt;div class="mermaid"&gt;
sequenceDiagram
participant Test
participant Calculator
participant Add
participant Multiply
participant Memory
Test-&gt;&gt;Calculator: Calculate(5, 3)
Calculator-&gt;&gt;Add: Add(5, 3)
Add--&gt;&gt;Calculator: 8
Calculator-&gt;&gt;Multiply: Multiply(8, 2)
Multiply--&gt;&gt;Calculator: 16
Calculator-&gt;&gt;Memory: AddToMemory(16)
Calculator-&gt;&gt;Memory: GetMemory()
Memory--&gt;&gt;Calculator: 16
Calculator--&gt;&gt;Test: 16
&lt;/div&gt;
&lt;p&gt;The sequence diagram is convenient for understanding the sequence of actions: who calls whom, in what order, what data is passed. This is a classic UML representation familiar to all developers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Behavioral graph&lt;/strong&gt; represents the same data as a graph with numbered edges:&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph TD
test[TestCalculateWithTrace]
newCalc[NewCalculator]
calc[Calculator.Calculate]
add[Add]
mult[Multiply]
addMem[AddToMemory]
getMem[GetMemory]
test --&gt;|1| newCalc
test --&gt;|2| calc
calc --&gt;|3| add
calc --&gt;|4| mult
calc --&gt;|5| addMem
calc --&gt;|6| getMem
style test fill:#e1f5ff
style calc fill:#fff4e1
style add fill:#f0f0f0
style mult fill:#f0f0f0
&lt;/div&gt;
&lt;p&gt;The graph is more compact than the sequence diagram and better suited for analysis. Numbers on edges show call order.&lt;/p&gt;
&lt;p&gt;Key features of the behavioral graph:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Edges are numbered&lt;/strong&gt; - execution order is preserved&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multigraph&lt;/strong&gt; - there can be multiple edges between two nodes (if the function was called multiple times)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context-dependent&lt;/strong&gt; - shows a specific scenario, not all possible paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subgraph of structural graph&lt;/strong&gt; - each behavioral graph node exists in the structural graph&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="behavioral-architecture-coverage-metrics"&gt;Behavioral Architecture Coverage Metrics
&lt;/h3&gt;&lt;p&gt;Acceptance tests directly determine the completeness of behavioral architecture. Each acceptance test creates one context. The totality of all contexts is the complete behavioral architecture of the system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key metrics:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Component coverage:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;coverage = (called components) / (total components) * 100%
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For example, if the structural graph has N components and M components are called in acceptance tests, then coverage = M/N * 100%.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Number of contexts:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The more acceptance tests, the more contexts, the more complete coverage of different usage scenarios.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Critical path coverage:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not all components are equally important. Critical business scenarios can be marked and their coverage tracked separately.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dead code detection:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If a component is present in the structural graph but doesn&amp;rsquo;t appear in any context - it&amp;rsquo;s a candidate for removal. Either the code is dead or acceptance tests are lacking.&lt;/p&gt;
&lt;p&gt;In a real project, aim for 80%+ coverage of critical paths with acceptance tests.&lt;/p&gt;
&lt;h2 id="conclusion-two-views-of-architecture"&gt;Conclusion: Two Views of Architecture
&lt;/h2&gt;&lt;p&gt;In this article, I showed how to represent software system architecture through a graph data structure. Two types of graphs provide two different but complementary views of the system:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Structural graph&lt;/strong&gt; shows how code is organized: what components exist and how they can interact. This is a static picture of potential connections. Construction is automated through AST analysis of source code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Behavioral graph&lt;/strong&gt; shows how the system actually works: which components are called in specific scenarios and in what sequence. This is a dynamic picture of actual execution paths. Construction is automated through acceptance test tracing.&lt;/p&gt;
&lt;p&gt;Key difference: the structural graph contains ALL possible connections, behavioral - only those actually used in business scenarios.&lt;/p&gt;
&lt;h3 id="whats-next"&gt;What&amp;rsquo;s Next
&lt;/h3&gt;&lt;p&gt;Graphs themselves are just the foundation. The interesting part begins when we use them for architecture quality control.&lt;/p&gt;
&lt;p&gt;In subsequent articles of the series, I&amp;rsquo;ll show:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Validation of architectural rules&lt;/strong&gt; - how to check graph constraints: prohibition of circular dependencies, layered architecture control, call depth limits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graph theory metrics&lt;/strong&gt; - how to measure architecture quality through connectivity, centrality, modularity and other metrics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI-generated code control&lt;/strong&gt; - how to use graphs and metrics to prevent architectural degradation when developing with AI agents&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="tools"&gt;Tools
&lt;/h3&gt;&lt;p&gt;All tools for building architectural graphs are available in the open repository: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;github.com/mshogin/archlint&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The tool works with Go projects, but the approach is universal and applicable to any programming language.&lt;/p&gt;
&lt;p&gt;The project includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go code analyzer for building structural graphs&lt;/li&gt;
&lt;li&gt;Tracing library for building behavioral graphs&lt;/li&gt;
&lt;li&gt;Visualization generators (PlantUML, Mermaid)&lt;/li&gt;
&lt;li&gt;CI/CD integration examples&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Mikhail Shogin - About</title><link>https://mshogin.com/about/</link><pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate><guid>https://mshogin.com/about/</guid><description>&lt;img src="https://mshogin.com/about/uworkflow-team1.png" alt="Featured image of post Mikhail Shogin - About" /&gt;&lt;p&gt;I&amp;rsquo;m doing software development since 2004. From that time, I&amp;rsquo;ve done several projects, participated in another number of teams and played with many different technologies, programming languages and frameworks.&lt;/p&gt;
&lt;p&gt;Currently I work at Wildberries &amp;amp; Russ as Systems Architect in the platform employment domain. I oversee the financial perimeter: write-offs, penalties, disputes, and loss control.&lt;/p&gt;
&lt;p&gt;In parallel, I develop practices for architectural oversight, system analysis, and business analysis. My focus is on automating these processes and integrating AI tools into team workflows.&lt;/p&gt;
&lt;p&gt;Before that - IPONWEB (later acquired by Criteo), where I grew from Perl/Lua developer to Systems Architect of Commerce Grid.&lt;/p&gt;
&lt;p&gt;Over these years I developed a simple algorithm - three questions before any task:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Goal: what do I want to achieve?&lt;/li&gt;
&lt;li&gt;Reality: what do I know and don&amp;rsquo;t know?&lt;/li&gt;
&lt;li&gt;Action: what will I do right now?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="experience"&gt;Experience
&lt;/h2&gt;&lt;h3 id="wbjob---architecture---wildberries--russ"&gt;WBJob - Architecture - Wildberries &amp;amp; Russ
&lt;/h3&gt;&lt;p&gt;Building system analysis, business analysis and architecture into the development process. Together with a fellow architect and a team of analysts, we establish standards and integrate into processes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Main challenge:&lt;/strong&gt; embed three stages (business analysis, system analysis, architectural oversight) into the development process without increasing time-to-market.&lt;/p&gt;
&lt;h3 id="hrtech---digital-transformation---wildberries"&gt;HRTech - digital transformation - Wildberries
&lt;/h3&gt;&lt;p&gt;Joined Wildberries as Systems Architect and built HR Tech as a manageable engineering system: system analysis practice, architecture as code, transparent integrations and delivery quality - instead of &amp;ldquo;we agreed verbally and shipped&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I built as organizational-architectural foundation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Built system analysis department from scratch:&lt;/strong&gt; assembled the team, established the practice, and embedded system analysis into the development process (requirements elaboration, contracts, integration coordination, acceptance criteria).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implemented &amp;ldquo;Architecture as Code&amp;rdquo; approach:&lt;/strong&gt; documented services and their responsibilities, captured key decisions through ADRs, built a service map and dependencies as a maintainable artifact, not &amp;ldquo;knowledge in heads&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brought order to integrations:&lt;/strong&gt; consolidated chaotic &amp;ldquo;verbal&amp;rdquo; integrations and manual token provisioning into a formalized approach - with a unified integration service, rules, automation and traceability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Introduced testing culture:&lt;/strong&gt; launched testing practices where none existed, integrated checks into CI/CD pipeline, improved release predictability and change quality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drove major initiatives to completion:&lt;/strong&gt; took on large changes, drove them through teams and dependent stakeholders, closed &amp;ldquo;loose ends&amp;rdquo; rather than leaving them as eternal concepts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Key product domains:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HR Platform (HRPortal)&lt;/strong&gt; - single source of truth for employees (warehouse + office/IT).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ATS (Applicant Tracking System)&lt;/strong&gt; - recruiting and onboarding, reducing dependency on external provider (HeadFlow).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Team Management (WBTeam)&lt;/strong&gt; - team management: vacancy requests, notifications, approvals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compensation &amp;amp; Benefits (C&amp;amp;B)&lt;/strong&gt; - calculation automation, tariffication and financial risk control.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="internal-control--audit---sku-logistics---wildberries--russ"&gt;Internal Control &amp;amp; Audit - SKU logistics - Wildberries &amp;amp; Russ
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Accumulated SKU cost:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Architectural support for the system calculating accumulated service cost per item (SKU) across the entire Wildberries logistics chain: gate acceptance -&amp;gt; warehouse -&amp;gt; transport logistics -&amp;gt; pickup points. Each major stage consists of multiple processes, each adding operation cost. Understanding this picture provides a foundation for optimization - from individual operations to major processes (sorting, acceptance, last mile).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warehouse operations tariffication:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Architectural support for the tariffication system. Specifics: all operations (warehouse + transport) are tariffed and paid - hourly, per operation, various output schemes. Enormous number of rules, nuances and legacy. Main constraint: warehouse must always operate, downtime is unacceptable.&lt;/p&gt;
&lt;h3 id="commerce-grid---platform-architecture---criteo"&gt;Commerce Grid - platform architecture - Criteo
&lt;/h3&gt;&lt;p&gt;After IPONWEB was acquired by Criteo, I joined as Systems Architect to work on Commerce Grid - a retail media platform.&lt;/p&gt;
&lt;p&gt;My key contributions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Created the initial C-Grid architecture model and established collaborative architecture practices&lt;/li&gt;
&lt;li&gt;Led Kubernetes migration for critical services with minimal downtime&lt;/li&gt;
&lt;li&gt;Built integration testing environment with Docker-based infrastructure for local development and CI&lt;/li&gt;
&lt;li&gt;Implemented service mesh, monitoring, and observability solutions&lt;/li&gt;
&lt;li&gt;Established architecture review processes and cross-team collaboration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The platform enables retailers to monetize their digital properties through advertising while maintaining user experience and data privacy.&lt;/p&gt;
&lt;h3 id="devops--sre---diving-into-operations---criteo"&gt;DevOps &amp;amp; SRE - diving into operations - Criteo
&lt;/h3&gt;&lt;p&gt;Working as a developer, I often heard from devops: &amp;ldquo;this takes long&amp;rdquo;. Got curious - what takes so long? Dove into DevOps for a year and a half, fully focused on infrastructure tasks. Then heard the same from SRE - &amp;ldquo;complex, takes time&amp;rdquo;. Moved to SRE for another year.&lt;/p&gt;
&lt;p&gt;Figured out how it all works from the inside: Google Cloud, AWS, Terraform, CI/CD pipelines. Now I understand both sides - development and operations.&lt;/p&gt;
&lt;h3 id="bidcast---load-balancer-development---iponweb"&gt;BidCast - Load Balancer development - IPONWEB
&lt;/h3&gt;&lt;p&gt;One of the most complex projects. Two goals: decompose the BidSwitch monolith and test a hypothesis - can we build our own load balancer cheaper than Google/AWS.&lt;/p&gt;
&lt;p&gt;First version proved: our load balancer is cheaper to maintain. Then we started moving logic from BidSwitch to BidCast - everything not tied to state and database, offloading heavy code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Main achievement - AdTXT module:&lt;/strong&gt; developed my own data storage format that allowed loading 5-6 GB into process memory in ~1 second and searching in 10 nanoseconds. This enabled extracting functionality from BidSwitch and saving tens of thousands of dollars per month. BidCast didn&amp;rsquo;t even notice the new module performance-wise.&lt;/p&gt;
&lt;h3 id="bidswitch---monolith-decomposition-to-microservices---iponweb"&gt;BidSwitch - monolith decomposition to microservices - IPONWEB
&lt;/h3&gt;&lt;p&gt;Microservices were at peak popularity back then. Led the decomposition of BidSwitch monolith into microservices - created about 7 services behind an API Gateway.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it ended:&lt;/strong&gt; shut down the initiative. Microservices support turned out more expensive than monolith - need to grow teams, more people. With monolith one team ships features, maybe slower, but steadily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I gained:&lt;/strong&gt; lots of practices, hard-learned lessons, deep understanding of tradeoffs. Main microservices benefit - ability to completely rewrite a service in 1-2 weeks. Can&amp;rsquo;t do that with a monolith.&lt;/p&gt;
&lt;h3 id="uworkflow---django-monolith---iponweb"&gt;uWorkflow - Django monolith - IPONWEB
&lt;/h3&gt;&lt;p&gt;Django monolith designed like a LEGO constructor - lots of small components. The system configured itself on the fly from a given schema. Configuration driven development: managing objects and relations through OpenAPI-compatible schemas. Schema was the heart of the system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faster project delivery&lt;/li&gt;
&lt;li&gt;All code in one repository&lt;/li&gt;
&lt;li&gt;Small team supporting many projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Became experts in Python, Django and DRF.&lt;/p&gt;
&lt;h3 id="youzoo---social-network-for-pets---2-years-in-sea"&gt;YouZoo - social network for pets - 2 years in SEA
&lt;/h3&gt;&lt;p&gt;Spent two years traveling across Myanmar, Thailand, Laos, Vietnam, Cambodia, Malaysia, Indonesia, the Philippines, Nepal, India, and Sri Lanka.&lt;/p&gt;
&lt;p&gt;During this time, I focused on deep self-learning and skill-building:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learned Python and built a small social network for pet owners&lt;/li&gt;
&lt;li&gt;Studied PostgreSQL and understood how to model and query structured data&lt;/li&gt;
&lt;li&gt;Switched fully to Emacs, building my own productive workflows&lt;/li&gt;
&lt;li&gt;Taught myself blind typing in English - to code and write faster&lt;/li&gt;
&lt;li&gt;Developed clarity, focus, and the ability to learn independently - skills I rely on every day in architecture and engineering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This journey shaped not only how I live, but how I think.&lt;/p&gt;
&lt;h3 id="рассылки---email-marketing---mailru"&gt;Рассылки - email marketing - Mail.Ru
&lt;/h3&gt;&lt;p&gt;30-40 million personalized emails per day. Two main challenges: &lt;strong&gt;Mail sender&lt;/strong&gt; and &lt;strong&gt;Targeting machine&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mail sender&lt;/strong&gt; in Perl with event loop. Hardcore times: daemons, interprocess communication, sockets, synchronization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Targeting machine&lt;/strong&gt; - first AdTech experience. Personalized targeting for each email. Developed a data structure with custom hash function: checking all variants in O(1). AdCache was huge but worked super fast.&lt;/p&gt;
&lt;p&gt;Learned TDD on this project - been writing tests for all my code ever since.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="mission"&gt;Mission
&lt;/h2&gt;&lt;p&gt;Helping companies transform complex systems into manageable architecture with clear boundaries, reliable integrations, and predictable evolution.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t about beautiful diagrams or trendy frameworks. It&amp;rsquo;s about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers understanding where their responsibility ends&lt;/li&gt;
&lt;li&gt;Changes in one service not breaking ten others&lt;/li&gt;
&lt;li&gt;New team members being able to understand the system in days, not months&lt;/li&gt;
&lt;li&gt;Business being able to plan development knowing the real cost of changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Complexity is inevitable. Chaos is not.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="values"&gt;Values
&lt;/h2&gt;&lt;h3 id="clear-boundaries-of-responsibility"&gt;Clear boundaries of responsibility
&lt;/h3&gt;&lt;p&gt;Each component knows its zone and doesn&amp;rsquo;t intrude on others. When boundaries are blurred, any change becomes an archaeological dig - who uses this? who will this break?&lt;/p&gt;
&lt;h3 id="contracts-over-verbal-agreements"&gt;Contracts over verbal agreements
&lt;/h3&gt;&lt;p&gt;If an integration isn&amp;rsquo;t formally described, it doesn&amp;rsquo;t exist. API contracts, data schemas, SLAs - everything must be documented. &amp;ldquo;We agreed on this during a call&amp;rdquo; is not a contract.&lt;/p&gt;
&lt;h3 id="measurable-outcomes"&gt;Measurable outcomes
&lt;/h3&gt;&lt;p&gt;If you can&amp;rsquo;t measure it, you can&amp;rsquo;t improve it. Architecture metrics, test coverage, response time, coupling between modules - everything should be a number, not a feeling.&lt;/p&gt;
&lt;h3 id="reliability-by-default"&gt;Reliability by default
&lt;/h3&gt;&lt;p&gt;The system should work predictably, not &amp;ldquo;usually works&amp;rdquo;. Graceful degradation, retry policies, circuit breakers - not options, but baseline requirements.&lt;/p&gt;
&lt;h3 id="simplicity-and-evolvability"&gt;Simplicity and evolvability
&lt;/h3&gt;&lt;p&gt;Complexity grows only when truly necessary. Every abstraction must justify its existence. Three similar lines of code are better than a premature abstraction.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="philosophy"&gt;Philosophy
&lt;/h2&gt;&lt;h3 id="7030-approach"&gt;70/30 approach
&lt;/h3&gt;&lt;p&gt;Conservative-risk-oriented balance. 70% of decisions use proven, reliable approaches. 30% are controlled experiments with new technologies and methods.&lt;/p&gt;
&lt;p&gt;I work only with manageable risks. This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clear criteria for success and failure&lt;/li&gt;
&lt;li&gt;Rollback plan before starting changes&lt;/li&gt;
&lt;li&gt;Isolation of experiments from critical paths&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="context-over-templates"&gt;Context over templates
&lt;/h3&gt;&lt;p&gt;Good architecture starts with understanding context, not applying ready-made solutions. Each system is unique and requires its own approach.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Best practices&amp;rdquo; are someone else&amp;rsquo;s experience in someone else&amp;rsquo;s context. Useful to know, dangerous to copy blindly.&lt;/p&gt;
&lt;h3 id="explicit-boundaries-of-responsibility"&gt;Explicit boundaries of responsibility
&lt;/h3&gt;&lt;p&gt;Not just in code, but in processes. Who makes the decision? Who bears responsibility for consequences? Who has veto power?&lt;/p&gt;
&lt;p&gt;Blurred boundaries are a source of conflicts and decision paralysis.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="places-ive-been"&gt;Places I&amp;rsquo;ve been
&lt;/h2&gt;&lt;p&gt;Actually to remember all the places I&amp;rsquo;ve been is very difficult task and only my wife is able to help me with it. &lt;strong&gt;Thank you dear, I love you!&lt;/strong&gt;&lt;/p&gt;
&lt;iframe src="https://www.google.com/maps/d/u/0/embed?mid=1oqsyxGbRaVlxpoEV1Cn-hrTx-cU" width="100%" height="400px"&gt;&lt;/iframe&gt;</description></item><item><title>Working with Chaos in Architecture</title><link>https://mshogin.com/blog/working-with-chaos/</link><pubDate>Mon, 28 Apr 2025 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/working-with-chaos/</guid><description>&lt;img src="https://mshogin.com/blog/working-with-chaos/cover.en.svg" alt="Featured image of post Working with Chaos in Architecture" /&gt;&lt;p&gt;When you work with real systems, you quickly realize: most of the time you don&amp;rsquo;t start with a clean slate.&lt;/p&gt;
&lt;p&gt;You start with history, compromises, half-implemented ideas, and changing priorities.&lt;/p&gt;
&lt;p&gt;At first, it feels messy. But over time, you learn something important: clarity isn&amp;rsquo;t given - it&amp;rsquo;s created.&lt;/p&gt;
&lt;h2 id="what-working-with-chaotic-architectures-taught-me"&gt;What working with chaotic architectures taught me
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Listen before judging.&lt;/strong&gt; Every decision was made in a certain context. Understanding that context is more important than rushing to conclusions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Find patterns without forcing them.&lt;/strong&gt; Patterns exist almost everywhere, but you need to let them emerge rather than forcing their appearance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build small anchors in unstable ground.&lt;/strong&gt; When there&amp;rsquo;s a lot of uncertainty around, small steady steps are important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And most importantly - stay patient with complexity.&lt;/strong&gt; Complexity is not the enemy. It&amp;rsquo;s reality that you need to learn to work with.&lt;/p&gt;
&lt;h2 id="every-messy-system-holds-a-story"&gt;Every messy system holds a story
&lt;/h2&gt;&lt;p&gt;And architecture, at its best, is about understanding that story and helping write the next chapter a little better.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re also working in the middle of chaos: you&amp;rsquo;re not doing it wrong. Most likely, you&amp;rsquo;re exactly where real architecture starts.&lt;/p&gt;</description></item><item><title/><link>https://mshogin.com/notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/</guid><description>&lt;h1 id="принял-4-проекта-в-надзор-делюсь-процессом-приёмки-и-аудита"&gt;Принял 4 проекта в надзор: делюсь процессом приёмки и аудита
&lt;/h1&gt;&lt;h2 id="tldr"&gt;TL;DR
&lt;/h2&gt;&lt;p&gt;Руководитель дал 4 новых проекта в архитектурный надзор. Держать всё в голове нереально. Изучил индустриальные практики и подготовил процесс приёмки совместно с Claude Code. Выложил в open-source. Буду рад feedback от вас и ваших агентов.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="как-всё-началось"&gt;Как всё началось
&lt;/h2&gt;&lt;p&gt;Руководитель: &amp;ldquo;Вот тебе 4 проекта - принимай в работу.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Я: &amp;ldquo;Окей&amp;hellip; А что там?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Руководитель: &amp;ldquo;Узнаешь.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Контест:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4 проекта&lt;/li&gt;
&lt;li&gt;Где-то есть пересечение функциональности (где именно - неясно)&lt;/li&gt;
&lt;li&gt;Команды разные, стек разный, зрелость разная&lt;/li&gt;
&lt;li&gt;Держать всё это в голове - бесмысленно&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Немного поглядел - стало понятно: нужен системный подход.&lt;/p&gt;
&lt;h2 id="что-я-сделал"&gt;Что я сделал
&lt;/h2&gt;&lt;h3 id="1-изучил-индустриальные-практики"&gt;1. Изучил индустриальные практики
&lt;/h3&gt;&lt;p&gt;Посмотрел, как это делают:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/futurice/project-handover-checklist" target="_blank" rel="noopener"
&gt;Futurice Project Handover Checklist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TOGAF Architecture Review&lt;/li&gt;
&lt;li&gt;Harvard EA Checklist&lt;/li&gt;
&lt;li&gt;Практики из книг (Software Architecture in Practice, Building Evolutionary Architectures)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-собрал-процесс-приёмки-и-аудита"&gt;2. Собрал процесс приёмки и аудита
&lt;/h3&gt;&lt;p&gt;Готовил совместно с Claude Code. Не в чистом виде, конечно - с моей конфигурацией (на текущий момент это 3882 строк rules, skills and commands). Безусловно, вычитывал и редактировал.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Что получилось:&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="процесс-приёмки-проекта"&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;Процесс приёмки проекта&lt;/a&gt;
&lt;/h4&gt;&lt;p&gt;6 фаз:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Инициация&lt;/strong&gt; (получить вводную, доступы)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kickoff встреча&lt;/strong&gt; (PM + Tech Lead)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сбор информации&lt;/strong&gt; (документация, код, мониторинг)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Аудит&lt;/strong&gt; (анализ архитектуры)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Решение о приёмке&lt;/strong&gt; (принят/с оговорками/не принят)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Онбординг в надзор&lt;/strong&gt; (регулярные встречи, точки контроля)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Файлы:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/templates/project-handover/project-handover-process.md" target="_blank" rel="noopener"
&gt;project-handover-process.md&lt;/a&gt; - детальный процесс&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/templates/project-handover/project-handover.md" target="_blank" rel="noopener"
&gt;project-handover.md&lt;/a&gt; - чеклист (11 секций, 80+ пунктов)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="шаблоны-аудита-системы"&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;Шаблоны аудита системы&lt;/a&gt;
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Ручной аудит&lt;/strong&gt; (12 разделов):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Структура системы (C4, bounded contexts)&lt;/li&gt;
&lt;li&gt;Взаимодействие сервисов (sync/async, матрица зависимостей)&lt;/li&gt;
&lt;li&gt;Паттерны и антипаттерны&lt;/li&gt;
&lt;li&gt;Observability (метрики, логи, трейсинг, алерты)&lt;/li&gt;
&lt;li&gt;Устойчивость (SPOF, graceful degradation, DR)&lt;/li&gt;
&lt;li&gt;Безопасность&lt;/li&gt;
&lt;li&gt;План улучшений&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Автоматическая валидация&lt;/strong&gt; (215 метрик):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coupling и fan-out&lt;/li&gt;
&lt;li&gt;Layer violations&lt;/li&gt;
&lt;li&gt;God classes&lt;/li&gt;
&lt;li&gt;Циклические зависимости&lt;/li&gt;
&lt;li&gt;Топологические метрики&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Файлы:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/templates/system-audit/system-audit.md" target="_blank" rel="noopener"
&gt;system-audit.md&lt;/a&gt; - ручной аудит&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/templates/system-audit/audit.md" target="_blank" rel="noopener"
&gt;audit.md&lt;/a&gt; - отчет автоматической валидации&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-статус"&gt;3. Статус
&lt;/h3&gt;&lt;p&gt;На следующей неделе начинаю приёмку. Посмотрим как процесс сработает в реальности.&lt;/p&gt;
&lt;p&gt;Если эксперимент удастся - расскажу подробнее о результатах, подводных камнях и корректировках процесса.&lt;/p&gt;
&lt;h2 id="вопрос-к-сообществу"&gt;Вопрос к сообществу
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Буду рад feedback от вас и ваших агентов:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Процесс:&lt;/strong&gt; Что лишнее? Чего не хватает?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Чеклисты:&lt;/strong&gt; Какие критичные пункты я упустил?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Автоматизация:&lt;/strong&gt; Используете ли инструменты для валидации архитектуры?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Агенты:&lt;/strong&gt; Если вы используете AI-агентов для аудита - какие задачи им даёте? Как проверяете результаты?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Open-source шаблоны:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;Project Handover&lt;/a&gt; - процесс и чеклист приёмки&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;System Audit&lt;/a&gt; - ручной и автоматический аудит&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/specifications" target="_blank" rel="noopener"
&gt;Specifications&lt;/a&gt; - spec-driven development&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/adr" target="_blank" rel="noopener"
&gt;ADR&lt;/a&gt; - Architecture Decision Records&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;С удовольствием улучшу на основе вашего опыта.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;UPD:&lt;/strong&gt; Если интересно как процесс сработал на практике - подписывайтесь, расскажу после завершения приёмки.
Telegram: &lt;a class="link" href="https://t.me/MikeShogin" target="_blank" rel="noopener"
&gt;https://t.me/MikeShogin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;#архитектура #процессы #opensource #claudecode&lt;/p&gt;</description></item><item><title/><link>https://mshogin.com/notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/</guid><description>&lt;h1 id="материалы-для-публикации-project-handover-templates"&gt;Материалы для публикации: Project Handover Templates
&lt;/h1&gt;&lt;p&gt;Посты о процессе приёмки проектов в архитектурное курирование.&lt;/p&gt;
&lt;h2 id="файлы"&gt;Файлы
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;telegram-post.md&lt;/code&gt; - пост для Telegram канала @MikeShogin&lt;/li&gt;
&lt;li&gt;&lt;code&gt;habr-post.md&lt;/code&gt; - статья для Habr&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="статус"&gt;Статус
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Шаблоны созданы и структурированы в archlint/templates&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Посты подготовлены&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Опубликовано в Telegram&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Опубликовано на Habr&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Большая статья для mshogin.ru (опционально, после приёмки проектов)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ссылки-на-шаблоны"&gt;Ссылки на шаблоны
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;Project Handover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;System Audit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/specifications" target="_blank" rel="noopener"
&gt;Specifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/adr" target="_blank" rel="noopener"
&gt;ADR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="план"&gt;План
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Опубликовать короткие посты (Telegram + Habr)&lt;/li&gt;
&lt;li&gt;Начать приёмку проектов на следующей неделе&lt;/li&gt;
&lt;li&gt;После завершения приёмки - написать большую статью с реальным опытом и подводными камнями&lt;/li&gt;
&lt;li&gt;Обновить шаблоны на основе практики&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="теги"&gt;Теги
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Telegram:&lt;/strong&gt; #архитектура #systemaudit #claudecode
&lt;strong&gt;Habr:&lt;/strong&gt; #архитектура #процессы #opensource #claudecode&lt;/p&gt;</description></item><item><title/><link>https://mshogin.com/notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/</guid><description>&lt;h1 id="пост-для-telegram"&gt;Пост для Telegram
&lt;/h1&gt;&lt;p&gt;Как принять 4 проекта в курирование и не свихнуться?&lt;/p&gt;
&lt;p&gt;Делюсь насущным. На кураторство упало 4 новых проекта. В какой-то момент стало понятно, что держать всё в голове просто бессмысленно - бизнес функции пересекаются, технололии разные .&lt;/p&gt;
&lt;p&gt;Я быстро осознал: вручную я это не вывезу. Чтобы спасти ситуацию, я решил опереться на индустриальные стандарты (Futurice, TOGAF, Harvard EA) и собрать системный процесс приёмки и аудита.&lt;/p&gt;
&lt;p&gt;Что мы разработали вместе с Claude Code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Процесс приёмки (6 фаз)&lt;/li&gt;
&lt;li&gt;Чеклист (11 секций, 80+ пунктов)&lt;/li&gt;
&lt;li&gt;Шаблон аудита (12 разделов)&lt;/li&gt;
&lt;li&gt;Автоматическая валидация (215 метрик)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Это была плотная работа.&lt;/p&gt;
&lt;p&gt;Пока теория. На следующей неделе начинаю приёмку - посмотрим что сломается в реальности.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ознакомиться можно здесь:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Процесс приёмки: &lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/project-handover" target="_blank" rel="noopener"
&gt;https://github.com/mshogin/archlint/tree/main/templates/project-handover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Аудит систем: &lt;a class="link" href="https://github.com/mshogin/archlint/tree/main/templates/system-audit" target="_blank" rel="noopener"
&gt;https://github.com/mshogin/archlint/tree/main/templates/system-audit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Как вы принимаете проекты? И юзаете ли AI для аудита?&lt;/p&gt;
&lt;p&gt;С удовольствием улучшу.&lt;/p&gt;
&lt;p&gt;#архитектура #systemaudit #claudecode&lt;/p&gt;</description></item><item><title>Archives</title><link>https://mshogin.com/archives/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/archives/</guid><description/></item><item><title>Contacts</title><link>https://mshogin.com/contacts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/contacts/</guid><description>&lt;h2 id="social-media"&gt;Social Media
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Telegram&lt;/strong&gt;: &lt;a class="link" href="https://t.me/MikeShogin" target="_blank" rel="noopener"
&gt;@MikeShogin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a class="link" href="https://github.com/mshogin" target="_blank" rel="noopener"
&gt;mshogin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;: &lt;a class="link" href="https://www.linkedin.com/in/mshogin/" target="_blank" rel="noopener"
&gt;mshogin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="business-details"&gt;Business Details
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Individual Entrepreneur Shogin Mikhail Mikhailovich&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Registration Number (OGRN)&lt;/strong&gt;: 323508100081596&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tax ID (INN)&lt;/strong&gt;: 504416750702&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ecosystem</title><link>https://mshogin.com/ecosystem/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/ecosystem/</guid><description>&lt;h2 id="geniearchi---ai-agent-linter-ecosystem"&gt;GenieArchi - AI Agent Linter Ecosystem
&lt;/h2&gt;&lt;p&gt;Quality, cost, and safety control for AI agent workflows. All Go + Rust, no LLM, under 10ms.&lt;/p&gt;
&lt;h3 id="pipeline"&gt;Pipeline
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;prompt -&amp;gt; seclint (safety) -&amp;gt; promptlint (routing) -&amp;gt; agent -&amp;gt; archlint (quality) -&amp;gt; costlint (cost)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="tools"&gt;Tools
&lt;/h3&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Repo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;archlint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Architecture linter - SOLID violations, cycles, fan-out&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;mshogin/archlint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;promptlint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prompt complexity scoring, model routing&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/mikeshogin/promptlint" target="_blank" rel="noopener"
&gt;mikeshogin/promptlint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;costlint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Token cost analysis, caching, A/B tests&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/mikeshogin/costlint" target="_blank" rel="noopener"
&gt;mikeshogin/costlint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;seclint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Content filter, age ratings (6+/12+/16+/18+)&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/mikeshogin/seclint" target="_blank" rel="noopener"
&gt;mikeshogin/seclint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GenieArchi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Umbrella project&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/mikeshogin/geniearchi" target="_blank" rel="noopener"
&gt;mikeshogin/geniearchi&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="numbers"&gt;Numbers
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;58% cost savings through intelligent routing&lt;/li&gt;
&lt;li&gt;Under 10ms per analysis&lt;/li&gt;
&lt;li&gt;Go + Rust (archlint-rs: single binary)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="services"&gt;Services
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Architecture Audit&lt;/strong&gt; - scan your project, find violations, get report&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt; - route simple tasks to cheap models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR Architecture Review&lt;/strong&gt; - automated arch diff on every PR&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Ecosystem Setup&lt;/strong&gt; - full pipeline in days&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="partners"&gt;Partners
&lt;/h3&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/kgatilin/myhome" target="_blank" rel="noopener"
&gt;myhome&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Workspace management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/kgatilin/deskd" target="_blank" rel="noopener"
&gt;deskd&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Agent runtime (Rust)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://github.com/kgatilin/nassau" target="_blank" rel="noopener"
&gt;nassau&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Governance rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Events</title><link>https://mshogin.com/events/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/events/</guid><description>&lt;h2 id="upcoming-events"&gt;Upcoming Events
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://lasmart.ru/webinar-data-catalog" target="_blank" rel="noopener"
&gt;Why Data Catalog Brings No Value&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Free online webinar about typical data catalog implementation mistakes and how AI can transform documentation workflows. Speaker: Pavel Khamrin.&lt;/td&gt;
&lt;td&gt;February 10, 2026, 11:00 AM MSK&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Notes</title><link>https://mshogin.com/notes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/</guid><description/></item><item><title>Resources</title><link>https://mshogin.com/resources/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/resources/</guid><description>&lt;h2 id="personal-blogs"&gt;Personal Blogs
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Author&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Links&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mikhail Shogin&lt;/td&gt;
&lt;td&gt;Systems Architect at Wildberries &amp;amp; Russ. Working with real systems, helping find patterns where there seems to be only chaos. Experience: Wildberries, Criteo, IPONWEB, Mail.Ru.&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/MikeShogin" target="_blank" rel="noopener"
&gt;Telegram&lt;/a&gt;, &lt;a class="link" href="https://mshogin.ru" target="_blank" rel="noopener"
&gt;Website&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sergey Baranov&lt;/td&gt;
&lt;td&gt;Architect, producer of ArchDays conference&lt;/td&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/blog_sb" target="_blank" rel="noopener"
&gt;Telegram&lt;/a&gt;, &lt;a class="link" href="https://archdays.ru" target="_blank" rel="noopener"
&gt;Website&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="telegram-channels"&gt;Telegram Channels
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/emacsway_log" target="_blank" rel="noopener"
&gt;@emacsway_log&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, Extreme Programming, SDLC, Agile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/it_arch" target="_blank" rel="noopener"
&gt;@it_arch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Discussions about enterprise information systems architecture (enterprise architecture, IT solutions architecture)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/plant_uml" target="_blank" rel="noopener"
&gt;@plant_uml&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Discussing PlantUML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/dochubchannel" target="_blank" rel="noopener"
&gt;@dochubchannel&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Architecture as Code approach and DocHub tool. &lt;a class="link" href="https://dochub.info" target="_blank" rel="noopener"
&gt;Website&lt;/a&gt;, &lt;a class="link" href="https://github.com/DocHubTeam/DocHub" target="_blank" rel="noopener"
&gt;GitHub&lt;/a&gt;, &lt;a class="link" href="https://github.com/rpiontik/DocHubExamples" target="_blank" rel="noopener"
&gt;Examples&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://t.me/analyst_job" target="_blank" rel="noopener"
&gt;@analyst_job&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Job postings and resumes for analysts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="websites"&gt;Websites
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://dckms.github.io/system-architecture/" target="_blank" rel="noopener"
&gt;dckms - System Architecture&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Materials on system architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a class="link" href="https://archdays.ru" target="_blank" rel="noopener"
&gt;ArchDays&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Conference for architects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Search</title><link>https://mshogin.com/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://mshogin.com/search/</guid><description/></item></channel></rss>