<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Architecture on Mikhail Shogin</title><link>https://mshogin.com/tags/architecture/</link><description>Recent content in Architecture on Mikhail Shogin</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Mikhail Shogin</copyright><lastBuildDate>Sat, 25 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mshogin.com/tags/architecture/index.xml" rel="self" type="application/rss+xml"/><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>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>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>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></channel></rss>