<?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/categories/architecture/</link><description>Recent content in Architecture on Mikhail Shogin</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Mikhail Shogin</copyright><lastBuildDate>Tue, 24 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mshogin.com/categories/architecture/index.xml" rel="self" type="application/rss+xml"/><item><title>AI Agent Linter Ecosystem: Quality, Cost and Safety Control</title><link>https://mshogin.com/blog/ai-linter-ecosystem/</link><pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/blog/ai-linter-ecosystem/</guid><description>&lt;h2 id="the-problem"&gt;The Problem
&lt;/h2&gt;&lt;p&gt;AI agents write code fast, but speed comes at a cost. Literally - tokens cost money. And figuratively - code quality degrades without oversight.&lt;/p&gt;
&lt;p&gt;I hit three problems at once:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Architecture degrades&lt;/strong&gt; - agents write working code that violates layer boundaries, creates circular dependencies and god classes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Costs grow&lt;/strong&gt; - complex prompts go to Opus at $15/1M tokens when Haiku at $0.80 would suffice&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content isn&amp;rsquo;t filtered&lt;/strong&gt; - production prompts contain things that shouldn&amp;rsquo;t be there&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each problem has its own tool. But when the tools work together, they amplify each other.&lt;/p&gt;
&lt;h2 id="the-pipeline"&gt;The Pipeline
&lt;/h2&gt;&lt;p&gt;Every request passes through a chain of linters, each responsible for its domain:&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph LR
A[Prompt] --&gt; B[seclint]
B --&gt;|safe| C[promptlint]
B --&gt;|blocked| X[Reject]
C --&gt;|haiku| D1[Agent: Haiku]
C --&gt;|sonnet| D2[Agent: Sonnet]
C --&gt;|opus| D3[Agent: Opus]
D1 --&gt; E[archlint]
D2 --&gt; E
D3 --&gt; E
E --&gt;|pass| F[costlint]
E --&gt;|fail| C
F --&gt; G[Done]
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;seclint&lt;/strong&gt; - checks content safety (6+/12+/16+/18+ ratings)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;promptlint&lt;/strong&gt; - scores complexity, picks the model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent&lt;/strong&gt; - executes the task on the selected model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;archlint&lt;/strong&gt; - validates the result for architecture violations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;costlint&lt;/strong&gt; - records cost, tracks cache hit rate&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If archlint rejects the result, the task escalates to a more powerful model. costlint records the escalation cost.&lt;/p&gt;
&lt;h2 id="the-tools"&gt;The Tools
&lt;/h2&gt;&lt;h3 id="archlint---architecture-linter"&gt;archlint - Architecture Linter
&lt;/h3&gt;&lt;p&gt;Scans Go projects for structural violations.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;archlint scan --format json ./project/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;What it finds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Layer violations (handler calls repository directly)&lt;/li&gt;
&lt;li&gt;God classes (&amp;gt;20 methods or &amp;gt;15 dependencies)&lt;/li&gt;
&lt;li&gt;Circular dependencies&lt;/li&gt;
&lt;li&gt;Interface Segregation violations (interfaces &amp;gt;5 methods)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Metrics: fan-out, coupling (Ca/Ce), component and link counts.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;mshogin/archlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="promptlint---complexity-based-router"&gt;promptlint - Complexity-Based Router
&lt;/h3&gt;&lt;p&gt;Scores prompt complexity and picks the model. No LLM, pure metrics, &amp;lt;10ms.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Fix typo in README&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; promptlint analyze --output-model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# haiku&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Design microservices with CQRS&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; promptlint analyze --output-model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# opus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Signals: length, sentence count, domain keywords, action type (fix/create/refactor), code presence.&lt;/p&gt;
&lt;p&gt;Integrates with ccproxy for real Claude Code request routing through a proxy.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/promptlint" target="_blank" rel="noopener"
&gt;mikeshogin/promptlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="costlint---token-cost-analysis"&gt;costlint - Token Cost Analysis
&lt;/h3&gt;&lt;p&gt;Tracks spending, analyzes caching, runs A/B tests between models.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;costlint report --source telemetry.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cost Report:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Total requests: 342
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; By model:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; opus: 48 requests, ~$12.60
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sonnet: 195 requests, ~$6.50
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; haiku: 99 requests, ~$0.44
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; With optimal routing: ~$8.20 (savings: 58%)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cache metrics: hit rate, block reuse, content entropy, Jaccard similarity.
A/B testing: 30/30/40 traffic split, per-group cost and quality metrics.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/costlint" target="_blank" rel="noopener"
&gt;mikeshogin/costlint&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="seclint--promptsec---content-filter"&gt;seclint / promptsec - Content Filter
&lt;/h3&gt;&lt;p&gt;Age ratings for prompts: 6+, 12+, 16+, 18+.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Help with math homework&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; seclint rate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# {&amp;#34;rating&amp;#34;: &amp;#34;6+&amp;#34;, &amp;#34;safe&amp;#34;: true}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Explain SQL injection for security course&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; seclint rate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# {&amp;#34;rating&amp;#34;: &amp;#34;16+&amp;#34;, &amp;#34;safe&amp;#34;: true, &amp;#34;flags&amp;#34;: [&amp;#34;security_tools&amp;#34;]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Considers educational context - explaining SQL injection for a security course gets 16+ instead of 18+.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a class="link" href="https://github.com/mikeshogin/seclint" target="_blank" rel="noopener"
&gt;mikeshogin/seclint&lt;/a&gt; / &lt;a class="link" href="https://github.com/mikeshogin/promptsec" target="_blank" rel="noopener"
&gt;mikeshogin/promptsec&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="shared-principles"&gt;Shared Principles
&lt;/h2&gt;&lt;p&gt;All tools follow the same rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go&lt;/strong&gt; - single stack, single build&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No LLM&lt;/strong&gt; - pure metrics, regex, keyword matching. &amp;lt;10ms per request&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI + HTTP&lt;/strong&gt; - each tool works as a command and as a server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSONL telemetry&lt;/strong&gt; - unified log format for analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipeline-friendly&lt;/strong&gt; - exit codes, stdout, pipes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="numbers"&gt;Numbers
&lt;/h2&gt;&lt;p&gt;On test workload (342 requests over a week):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Token spending&lt;/td&gt;
&lt;td&gt;$19.54&lt;/td&gt;
&lt;td&gt;$8.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture violations&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests to expensive model&lt;/td&gt;
&lt;td&gt;100% opus&lt;/td&gt;
&lt;td&gt;14% opus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing latency&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&amp;lt;10ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;58% cost savings without quality loss - simple tasks go to Haiku, architecture tasks stay on Opus.&lt;/p&gt;
&lt;h2 id="orchestration"&gt;Orchestration
&lt;/h2&gt;&lt;p&gt;The tools work autonomously, but deliver maximum impact together. For orchestration we use &lt;a class="link" href="https://github.com/kgatilin/myhome" target="_blank" rel="noopener"
&gt;myhome&lt;/a&gt; - daemon-based AI agent management with workflow stages and scheduled tasks.&lt;/p&gt;
&lt;p&gt;The stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;myhome launches agents&lt;/li&gt;
&lt;li&gt;promptlint picks the model (pre-route hook)&lt;/li&gt;
&lt;li&gt;archlint validates output (quality gate stage)&lt;/li&gt;
&lt;li&gt;costlint tracks cost (telemetry consumer)&lt;/li&gt;
&lt;li&gt;seclint filters incoming prompts (pre-filter)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="get-started"&gt;Get Started
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install all tools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mshogin/archlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/promptlint/cmd/promptlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/costlint/cmd/costlint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go install github.com/mikeshogin/seclint/cmd/seclint@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Start routing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;promptlint serve &lt;span class="m"&gt;8090&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;seclint serve &lt;span class="m"&gt;8091&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check architecture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;archlint scan --format json ./my-project/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# View costs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;costlint report --source ~/.promptlint/telemetry.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="links"&gt;Links
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;archlint&lt;/a&gt; - architecture linter&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/promptlint" target="_blank" rel="noopener"
&gt;promptlint&lt;/a&gt; - complexity router&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/costlint" target="_blank" rel="noopener"
&gt;costlint&lt;/a&gt; - cost analysis&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mikeshogin/seclint" target="_blank" rel="noopener"
&gt;seclint&lt;/a&gt; / &lt;a class="link" href="https://github.com/mikeshogin/promptsec" target="_blank" rel="noopener"
&gt;promptsec&lt;/a&gt; - content filter&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kgatilin/myhome" target="_blank" rel="noopener"
&gt;myhome&lt;/a&gt; - agent orchestration&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/mshogin/archlint/blob/main/ECOSYSTEM.md" target="_blank" rel="noopener"
&gt;ECOSYSTEM.md&lt;/a&gt; - integration map&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>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: Reproduce a project from specs alone</title><link>https://mshogin.com/notes/archlint-reproduction/</link><pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate><guid>https://mshogin.com/notes/archlint-reproduction/</guid><description>&lt;p&gt;Ran an experiment: can you reproduce a project if you give AI only specifications without source code?&lt;/p&gt;
&lt;h2 id="setup"&gt;Setup
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Original project: &lt;a class="link" href="https://github.com/mshogin/archlint" target="_blank" rel="noopener"
&gt;archlint&lt;/a&gt; - a Go architecture analysis tool&lt;/li&gt;
&lt;li&gt;Input: &lt;strong&gt;10 specifications&lt;/strong&gt; (Markdown + PlantUML), totaling &lt;strong&gt;73 KB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Claude Code received an empty directory and specs&lt;/li&gt;
&lt;li&gt;Executor: Claude Code, started in an &lt;strong&gt;empty directory&lt;/strong&gt; and implemented the project from scratch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Specs covered all the basics: module init, Makefile, data model, Go-analyzer, Cobra CLI, &lt;code&gt;collect&lt;/code&gt;/&lt;code&gt;trace&lt;/code&gt; commands, tracer library, tracelint, and integration tests.&lt;/p&gt;
&lt;h2 id="time"&gt;Time
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;~20 minutes&lt;/strong&gt; from empty directory to working project.&lt;/p&gt;
&lt;h2 id="results"&gt;Results
&lt;/h2&gt;&lt;p&gt;Final assessment of the cloned repository:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Structural identity: 100%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloning success: 85.5%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semantic equivalence: ~75%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mutations: 23&lt;/strong&gt; (3 critical, 8 medium, 12 minor)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interesting detail: the clone turned out &lt;strong&gt;shorter&lt;/strong&gt; than the original - 1,845 lines of Go vs 2,159 (-14.5%) with the same number of &lt;code&gt;.go&lt;/code&gt; files (13).&lt;/p&gt;
&lt;h2 id="mutations-that-actually-matter"&gt;Mutations that actually matter
&lt;/h2&gt;&lt;p&gt;Three &amp;ldquo;critical&amp;rdquo; mutations - exactly the places where the specification leaves room for interpretation (i.e., for creativity you didn&amp;rsquo;t order):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sequence diagram building:&lt;/strong&gt; changed the algorithm for forming calls in the diagram (logic for call stack and write conditions).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tracerlint:&lt;/strong&gt; clone considers deprecated &lt;code&gt;Exit()&lt;/code&gt; call acceptable, while the original does not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GoAnalyzer:&lt;/strong&gt; added &lt;code&gt;baseDir&lt;/code&gt; and &lt;code&gt;modulePath&lt;/code&gt; fields - AI &amp;ldquo;improved&amp;rdquo; the model because the specs didn&amp;rsquo;t explicitly define the analyzer&amp;rsquo;s responsibility boundary (what to store inside, what to compute outside).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="takeaway"&gt;Takeaway
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Spec-driven development works as a mechanism for reproducing the &amp;ldquo;functional core&amp;rdquo;.&lt;/strong&gt; 73 KB of specifications was enough to quickly restore structure and core functionality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Critical deviations occur where the specification describes &amp;ldquo;what should be&amp;rdquo; but doesn&amp;rsquo;t define &amp;ldquo;how to verify it&amp;rdquo;.&lt;/strong&gt; For such places you need:
&lt;ul&gt;
&lt;li&gt;precise rules (invariants),&lt;/li&gt;
&lt;li&gt;input/output examples,&lt;/li&gt;
&lt;li&gt;golden tests (byte-by-byte/structural comparison),&lt;/li&gt;
&lt;li&gt;prohibition on &amp;ldquo;model extension&amp;rdquo; without an explicit spec item.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In short: AI can clone a project from specs quickly. But if there&amp;rsquo;s a gap in the specs - it will definitely squeeze in some &amp;ldquo;engineering optimization&amp;rdquo;. Sometimes useful. In critical places - usually not.&lt;/p&gt;
&lt;p&gt;Clone repository: &lt;a class="link" href="https://github.com/mshogin/archlint-reproduction" target="_blank" rel="noopener"
&gt;mshogin/archlint-reproduction&lt;/a&gt;&lt;/p&gt;</description></item><item><title>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>