<?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 TurboVision</title>
    <link>https://turbovision.in6-addr.net/tags/architecture/</link>
    <description>Recent content in Architecture on TurboVision</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Tue, 21 Apr 2026 14:06:12 +0000</lastBuildDate>
    <atom:link href="https://turbovision.in6-addr.net/tags/architecture/index.xml" rel="self" type="application/rss&#43;xml" />
    
    
    
    <item>
      <title>From Prompt to Protocol Stack</title>
      <link>https://turbovision.in6-addr.net/musings/ai-language-protocols/from-prompt-to-protocol-stack/</link>
      <pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate>
      <lastBuildDate>Sat, 18 Apr 2026 00:00:00 +0000</lastBuildDate>
      <guid>https://turbovision.in6-addr.net/musings/ai-language-protocols/from-prompt-to-protocol-stack/</guid>
      <description>&lt;p&gt;The future of AI control was never going to fit inside one clever paragraph typed into a chat box. What looks like prompting today is already breaking apart into layers, and each layer is quietly starting to serve a different audience: humans, agents, tools, infrastructure, and, eventually, other layers pretending not to be there.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Prompting is evolving into a full protocol stack. Natural language remains at the human boundary, while deeper layers increasingly carry schemas, tool definitions, memory layouts, compressed state, and possibly machine-native agent communication. The chat box survives, but it is no longer the whole machine.&lt;/p&gt;
&lt;h2 id=&#34;the-question&#34;&gt;The Question&lt;/h2&gt;
&lt;p&gt;Have you ever wondered whether we are still dealing with prompting at all once prompts become longer, more structured, and more system-like? Or are we actually watching a new software stack form around language models?&lt;/p&gt;
&lt;h2 id=&#34;the-long-answer&#34;&gt;The Long Answer&lt;/h2&gt;
&lt;p&gt;I think we are very obviously watching a new stack form, even if the industry still likes talking as though everything important happens inside the visible prompt.&lt;/p&gt;
&lt;h3 id=&#34;the-prompt-is-no-longer-the-whole-unit&#34;&gt;The Prompt Is No Longer the Whole Unit&lt;/h3&gt;
&lt;p&gt;The mistake is to imagine the prompt as the unit. That made some sense when language models were mostly single-turn text machines. It makes much less sense once we ask them to persist, use tools, collaborate, manage memory, or act inside workflows. At that point the useful object is no longer the prompt alone. It is the entire communication architecture around it.&lt;/p&gt;
&lt;p&gt;That architecture already has layers, even if we do not always name them consistently.&lt;/p&gt;
&lt;p&gt;At the top there is the human intention layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;goals&lt;/li&gt;
&lt;li&gt;tone&lt;/li&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;li&gt;questions&lt;/li&gt;
&lt;li&gt;examples&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where natural language shines. It is flexible, compresses messy intention well enough, and lets humans stay close to the task without dropping into low-level syntax immediately.&lt;/p&gt;
&lt;p&gt;Below that sits the behavioral framing layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;system instructions&lt;/li&gt;
&lt;li&gt;role definitions&lt;/li&gt;
&lt;li&gt;safety boundaries&lt;/li&gt;
&lt;li&gt;refusal rules&lt;/li&gt;
&lt;li&gt;escalation behavior&lt;/li&gt;
&lt;li&gt;evaluation priorities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This layer says less about the task itself and more about the posture the model should adopt while attempting the task.&lt;/p&gt;
&lt;p&gt;Below that sits the operational context layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;retrieved documents&lt;/li&gt;
&lt;li&gt;repository state&lt;/li&gt;
&lt;li&gt;conversation history&lt;/li&gt;
&lt;li&gt;persistent memory&lt;/li&gt;
&lt;li&gt;environment facts&lt;/li&gt;
&lt;li&gt;current artifacts under edit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This layer answers the question: what world is the agent acting inside?&lt;/p&gt;
&lt;p&gt;Below that sits the tool layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tool names&lt;/li&gt;
&lt;li&gt;schemas&lt;/li&gt;
&lt;li&gt;permissions&lt;/li&gt;
&lt;li&gt;invocation rules&lt;/li&gt;
&lt;li&gt;observation formats&lt;/li&gt;
&lt;li&gt;retry and failure policies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a model can act, tools stop being optional flavor and become part of the language of control.&lt;/p&gt;
&lt;p&gt;Below that sits the machine coordination layer, which is still young but increasingly visible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;compressed summaries&lt;/li&gt;
&lt;li&gt;state snapshots&lt;/li&gt;
&lt;li&gt;cache reuse&lt;/li&gt;
&lt;li&gt;structured intermediate outputs&lt;/li&gt;
&lt;li&gt;inter-agent messages&lt;/li&gt;
&lt;li&gt;latent or activation-based exchange&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the layer where ordinary prompting begins to blur into protocol engineering.&lt;/p&gt;
&lt;p&gt;And beneath all of that, of course, sits the model-internal representational machinery itself.&lt;/p&gt;
&lt;p&gt;If you lay the system out this way, a lot of contemporary confusion evaporates. People argue about prompting as though it were one thing. It is not. They are usually talking past each other about different layers and then acting surprised that the debate goes nowhere.&lt;/p&gt;
&lt;p&gt;One person means phrasing tricks in the user message.
Another means system prompt design.
Another means retrieval quality.
Another means JSON schemas.
Another means agent orchestration.
Another means &lt;a href=&#34;https://arxiv.org/abs/2410.12877&#34;&gt;activation steering&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All of those are &amp;ldquo;prompting&amp;rdquo; only in the broadest and least useful sense.&lt;/p&gt;
&lt;h3 id=&#34;the-layers-are-already-visible&#34;&gt;The Layers Are Already Visible&lt;/h3&gt;
&lt;p&gt;That is why I prefer the phrase protocol stack. It captures the architecture better and also suggests the future more honestly. It sounds less magical, which is exactly why I trust it more.&lt;/p&gt;
&lt;p&gt;A mature AI system will likely look something like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;human gives high-level intent in natural language&lt;/li&gt;
&lt;li&gt;system translates that intent into a stabilized task frame&lt;/li&gt;
&lt;li&gt;task frame binds relevant memory, documents, and tool affordances&lt;/li&gt;
&lt;li&gt;one or more agents execute subtasks under explicit protocols&lt;/li&gt;
&lt;li&gt;agents exchange summaries or compressed state internally&lt;/li&gt;
&lt;li&gt;final result is reprojected into human-legible language for review or approval&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice what changed. Natural language remains important, but it is no longer the whole medium. It becomes the topmost interface over deeper coordination channels.&lt;/p&gt;
&lt;p&gt;That is exactly how most successful technical systems evolve.&lt;/p&gt;
&lt;p&gt;A web browser gives you a page, not packets.
A database query gives you SQL, not disk head timing.
An operating system gives you processes, not transistor switching.&lt;/p&gt;
&lt;p&gt;The user gets a legible abstraction. Underneath, layers proliferate because raw freedom does not scale by itself.&lt;/p&gt;
&lt;p&gt;The AI case is especially interesting because language appears at both ends of the stack. We enter through language, we leave through language, and the machinery in the middle gets less and less obligated to stay conversational.&lt;/p&gt;
&lt;p&gt;At the entrance, language captures goals.
At the exit, language communicates results.
In the middle, however, language may become increasingly optional.&lt;/p&gt;
&lt;p&gt;That is where agent-to-agent communication becomes important. If two agents are solving a problem together, full natural-language exchange is often expensive. It is verbose, ambiguous, and tied to human readability. For some tasks that is still worth it, especially when auditability matters. For others it may prove wasteful compared to compressed intermediate forms.&lt;/p&gt;
&lt;p&gt;There is something faintly ridiculous in imagining two high-speed reasoning systems politely sending each other mini-essays in immaculate English simply because that is the only style of interaction humans currently find respectable. A lot of the future may consist of us slowly admitting that the internals do not actually want to be this literary.&lt;/p&gt;
&lt;p&gt;We are already seeing small previews of this future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;structured chain outputs instead of free prose&lt;/li&gt;
&lt;li&gt;schema-constrained responses&lt;/li&gt;
&lt;li&gt;tool-call argument objects&lt;/li&gt;
&lt;li&gt;reusable memory summaries&lt;/li&gt;
&lt;li&gt;vector-based &lt;a href=&#34;https://aclanthology.org/2021.emnlp-main.243/&#34;&gt;soft prompts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://arxiv.org/abs/2410.12877&#34;&gt;activation steering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;experimental latent communication between agents&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are not isolated hacks. They are early pieces of a layered control model, even if the marketing language around them still prefers the friendlier fiction that we are merely &amp;ldquo;improving prompting.&amp;rdquo;&lt;/p&gt;
&lt;h3 id=&#34;natural-language-becomes-the-top-layer&#34;&gt;Natural Language Becomes the Top Layer&lt;/h3&gt;
&lt;p&gt;A useful way to think about it is with a networking analogy, and yes, I know that analogy is a little nerdy. It is still better than pretending the chat transcript is the architecture.&lt;/p&gt;
&lt;p&gt;Human prompting today often behaves like application-layer traffic mixed together with transport, session, and routing concerns in the same blob of text. That is why prompts become huge and fragile. They are doing too many jobs at once. They describe the task, define policy, encode examples, specify output shape, explain tool behavior, and sometimes even embed recovery instructions.&lt;/p&gt;
&lt;p&gt;Anyone who has seen a &amp;ldquo;simple prompt&amp;rdquo; mutate into a 900-line system prompt with XML-ish delimiters, output schemas, tool instructions, refusal clauses, and five examples knows exactly how fast this happens. The thing still lives in a chat window, but it stopped being &amp;ldquo;just chatting&amp;rdquo; a long time ago.&lt;/p&gt;
&lt;p&gt;In a more mature stack, those concerns separate.&lt;/p&gt;
&lt;p&gt;The result should not be imagined as less human. It should be imagined as more disciplined. Humans still speak their goals in language, but the system no longer forces every single control concern to be expressed as prose in one monolithic block.&lt;/p&gt;
&lt;p&gt;This matters for engineering quality.&lt;/p&gt;
&lt;p&gt;Once layers separate, you can version them independently. You can test them independently. You can reason about failure more clearly. You can update tool schemas without rewriting the entire prompt universe. You can swap memory strategies or retrieval methods while keeping the top-level interaction stable.&lt;/p&gt;
&lt;p&gt;That is a major architectural gain.&lt;/p&gt;
&lt;p&gt;There is also a philosophical gain. It frees us from the false binary between &amp;ldquo;talking naturally&amp;rdquo; and &amp;ldquo;going back to code.&amp;rdquo; We are not simply bouncing between total informality and total formalism. We are building multi-layer systems where different degrees of formality belong in different places.&lt;/p&gt;
&lt;p&gt;The human should not be forced to express every intention in rigid syntax.
The machine should not be forced to carry every internal coordination step in human prose.&lt;/p&gt;
&lt;p&gt;The protocol stack allows both truths at once.&lt;/p&gt;
&lt;h3 id=&#34;layering-solves-problems-and-creates-new-ones&#34;&gt;Layering Solves Problems and Creates New Ones&lt;/h3&gt;
&lt;p&gt;Of course, the problems arrive immediately.&lt;/p&gt;
&lt;p&gt;Layering creates opacity. Once more control happens below the visible prompt, users may lose sight of what is actually governing behavior. Hidden system prompts, invisible retrieval, latent memory shaping, and inter-agent subprotocols can make the system powerful and less inspectable. Anyone serious about AI governance should worry about that, and not in a performative way.&lt;/p&gt;
&lt;p&gt;But that worry is not an argument against the stack. It is evidence that the stack is real.&lt;/p&gt;
&lt;p&gt;No one worries about invisible layers in a system that does not have them.&lt;/p&gt;
&lt;p&gt;In that sense, we are already past the era of naive prompting. The visible chat box survives, but it is increasingly the polite fiction that hides a much larger control apparatus.&lt;/p&gt;
&lt;p&gt;And that may be healthy. Computing has always needed boundary surfaces that are easier than the machinery beneath them. The mistake is only to confuse the surface with the whole machine, which is exactly what a lot of current discourse keeps doing.&lt;/p&gt;
&lt;p&gt;So are we still dealing with prompting?&lt;/p&gt;
&lt;p&gt;Yes, if by prompting we mean the top-level act of expressing intent to a language-shaped system.&lt;/p&gt;
&lt;p&gt;No, if by prompting we mean the full control problem.&lt;/p&gt;
&lt;p&gt;That full problem now belongs to protocol design, context architecture, tool governance, memory management, and eventually machine-native coordination.&lt;/p&gt;
&lt;p&gt;The prompt is not disappearing. It is being demoted from sovereign command to one layer in a growing stack, which is probably healthier for everyone except people who enjoyed pretending the prompt was the whole art.&lt;/p&gt;
&lt;p&gt;And that, in my view, is the beginning of a more mature understanding of what these systems really are.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;What we casually call prompting is already splitting into layers: human intent, behavioral framing, operational context, tool control, memory management, and machine coordination. Natural language remains crucial, but it no longer has to carry every control concern by itself. As systems mature, the visible prompt becomes less like a sovereign instruction and more like the top layer of a broader protocol architecture.&lt;/p&gt;
&lt;p&gt;That shift is not a loss of humanity. It is an increase in architectural honesty. The system is finally being described in the shape it actually has, rather than the shape the chat UI flatters us into seeing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Once we accept that the prompt is only the top layer of the stack, what should remain visible to the human user and what should never be hidden underneath?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Related reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/musings/ai-language-protocols/freedom-creates-protocol/&#34;&gt;Freedom Creates Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/musings/ai-language-protocols/is-there-a-hidden-language-beneath-english/&#34;&gt;Is There a Hidden Language Beneath English?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/musings/ai-language-protocols/the-real-historical-analogy/&#34;&gt;The Real Historical Analogy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Security Findings as Design Feedback</title>
      <link>https://turbovision.in6-addr.net/hacking/security-findings-as-design-feedback/</link>
      <pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate>
      <lastBuildDate>Sun, 22 Feb 2026 22:43:22 +0100</lastBuildDate>
      <guid>https://turbovision.in6-addr.net/hacking/security-findings-as-design-feedback/</guid>
      <description>&lt;p&gt;Security reports are often treated as defect inventories: patch issue, close ticket, move on. That workflow is necessary, but it is incomplete. Many findings are not isolated mistakes; they are design feedback about how a system creates, hides, or amplifies risk. Teams that only chase individual fixes improve slowly. Teams that read findings as architecture signals improve compoundingly.&lt;/p&gt;
&lt;p&gt;A useful reframing is to ask, for each vulnerability: what design decision made this class of bug easy to introduce and hard to detect? The answer is frequently broader than the code diff. Weak trust boundaries, inconsistent authorization checks, ambiguous ownership of validation, and hidden data flows are structural causes. Fixing one endpoint without changing those structures guarantees recurrence.&lt;/p&gt;
&lt;p&gt;Take broken access control patterns. A typical report may show one API endpoint missing a tenant check. The immediate patch adds the check. The design feedback, however, is that authorization is optional at call sites. The durable response is to move authorization into mandatory middleware or typed service contracts so bypassing it becomes difficult by construction. Good security design reduces optionality.&lt;/p&gt;
&lt;p&gt;Input-validation findings show similar dynamics. If every handler parses raw request bodies independently, validation drift is inevitable. One team sanitizes aggressively, another copies old logic, a third misses edge cases under deadline pressure. The root issue is distributed policy. Consolidated schemas, shared parsers, and fail-closed defaults turn ad-hoc validation into predictable infrastructure.&lt;/p&gt;
&lt;p&gt;Injection flaws often reveal boundary confusion rather than purely “bad escaping.” When query construction crosses multiple abstraction layers with mixed assumptions, responsibility blurs and dangerous concatenation appears. The design-level fix is not a lint rule alone. It is to constrain query creation to safe primitives and enforce typed interfaces that make unsafe composition visibly abnormal.&lt;/p&gt;
&lt;p&gt;Security findings also expose observability gaps. If exploitation attempts succeed silently or are detected only through external reports, the system lacks meaningful security telemetry. A mature response adds event streams for auth decisions, suspicious parameter patterns, and integrity checks, with dashboards tied to operational ownership. Detection is a design feature, not a post-incident add-on.&lt;/p&gt;
&lt;p&gt;Another pattern is privilege creep in internal services. A report might flag one misuse of a high-privilege token. The deeper signal is that privilege scopes are too broad and rotation or delegation models are weak. Architecture should prefer least-privilege tokens per task, short lifetimes, and explicit trust contracts between services. Otherwise the blast radius of ordinary mistakes remains unacceptable.&lt;/p&gt;
&lt;p&gt;Process design matters as much as runtime design. Findings discovered repeatedly in similar areas indicate review pathways that miss systemic risks. Security review should include “class analysis”: when one issue appears, search for siblings by pattern and subsystem. This turns isolated remediation into proactive hardening. Without class analysis, teams play vulnerability whack-a-mole forever.&lt;/p&gt;
&lt;p&gt;Prioritization also benefits from design thinking. Severity alone does not capture strategic value. A medium issue that reveals a widespread anti-pattern may deserve higher priority than a high-severity edge case with narrow reach. Decision frameworks should account for recurrence potential and architectural leverage, not just immediate exploitability metrics.&lt;/p&gt;
&lt;p&gt;Communication style influences whether findings drive design changes. Reports framed as blame trigger defensive behavior and minimal patches. Reports framed as system learning opportunities invite ownership and broader fixes. Precision still matters, but tone can determine whether teams engage deeply or optimize for closure speed.&lt;/p&gt;
&lt;p&gt;One practical method is a “finding-to-principle” review after each security cycle:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Summarize the concrete issue.&lt;/li&gt;
&lt;li&gt;Identify the enabling design condition.&lt;/li&gt;
&lt;li&gt;Define a preventive principle.&lt;/li&gt;
&lt;li&gt;Encode the principle in tooling, APIs, or architecture.&lt;/li&gt;
&lt;li&gt;Track recurrence as an outcome metric.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process converts incidents into institutional memory.&lt;/p&gt;
&lt;p&gt;Security maturity is not a state where no bugs exist. It is a state where each bug teaches the system to fail less in the future. That requires treating findings as feedback loops into design, not just repair queues for implementation. The difference between those mindsets determines whether risk decays or accumulates.&lt;/p&gt;
&lt;p&gt;In short: fix the bug, yes. But always ask what the bug is trying to teach your architecture. That question is where long-term resilience starts.&lt;/p&gt;
&lt;p&gt;Teams that institutionalize this mindset stop treating security as a parallel bureaucracy and start treating it as part of system design quality. Over time, this reduces not only exploit risk but also operational surprises, because clearer boundaries and explicit trust rules improve reliability for everyone, not just security reviewers.&lt;/p&gt;
&lt;h2 id=&#34;finding-to-principle-template&#34;&gt;Finding-to-principle template&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Finding: &amp;lt;concrete vulnerability&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Class: &amp;lt;auth / validation / injection / secrets / ...&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Enabling design condition: &amp;lt;what made this class likely&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Preventive principle: &amp;lt;design rule to encode&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Enforcement point: &amp;lt;middleware / schema / API contract / CI check&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Owner + deadline: &amp;lt;who and by when&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Recurrence metric: &amp;lt;how we detect class-level improvement&amp;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;This keeps remediation focused on recurrence reduction, not ticket closure optics.&lt;/p&gt;
&lt;p&gt;Related reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/hacking/threat-modeling-in-the-small/&#34;&gt;Threat Modeling in the Small&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/hacking/assumption-led-security-reviews/&#34;&gt;Assumption-Led Security Reviews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/musings/clarity-is-an-operational-advantage/&#34;&gt;Clarity Is an Operational Advantage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Turbo Pascal Units as Architecture, Not Just Reuse</title>
      <link>https://turbovision.in6-addr.net/retro/dos/tp/turbo-pascal-units-as-architecture/</link>
      <pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate>
      <lastBuildDate>Mon, 09 Mar 2026 09:46:27 +0100</lastBuildDate>
      <guid>https://turbovision.in6-addr.net/retro/dos/tp/turbo-pascal-units-as-architecture/</guid>
      <description>&lt;p&gt;Most people first meet Turbo Pascal units as &amp;ldquo;how to avoid copy-pasting procedures.&amp;rdquo; That is true and incomplete. In real projects, units are architecture boundaries. They define what the rest of the system is allowed to know, hide what can change, and make refactoring survivable under pressure.&lt;/p&gt;
&lt;p&gt;In constrained DOS projects, this was not academic design purity. It was the difference between shipping and debugging forever.&lt;/p&gt;
&lt;h2 id=&#34;interface-section-is-a-contract-surface&#34;&gt;Interface section is a contract surface&lt;/h2&gt;
&lt;p&gt;A good unit interface exposes minimal, stable operations. It does not leak storage details, timing internals, or helper routines with unclear ownership. You can read the interface as a capability map.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-pascal&#34; data-lang=&#34;pascal&#34;&gt;unit RenderCore;

interface
procedure BeginFrame;
procedure DrawSprite(X, Y, Id: Integer);
procedure EndFrame;

implementation
{ internal page selection, clipping, palette handling }
end.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice what is missing: page indices, raw VGA register details, sprite memory layout. Those remain private so callers cannot create illegal states casually.&lt;/p&gt;
&lt;h2 id=&#34;separation-patterns-that-work&#34;&gt;Separation patterns that work&lt;/h2&gt;
&lt;p&gt;A practical retro project often benefits from explicit layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SysCfg&lt;/code&gt;: startup profile, paths, feature flags&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Input&lt;/code&gt;: keyboard state and edge detection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RenderCore&lt;/code&gt;: page lifecycle and primitives&lt;/li&gt;
&lt;li&gt;&lt;code&gt;World&lt;/code&gt;: simulation and collision&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UiHud&lt;/code&gt;: overlays independent of camera&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each layer exports what the next layer needs, and no more.&lt;/p&gt;
&lt;p&gt;This is still modern architecture wisdom, just with smaller tools.&lt;/p&gt;
&lt;h2 id=&#34;compile-time-feedback-as-architecture-feedback&#34;&gt;Compile-time feedback as architecture feedback&lt;/h2&gt;
&lt;p&gt;One advantage of strong unit boundaries: breakage appears quickly at compile time. If you change a function signature in one interface, all dependent call sites surface immediately. That pressure encourages deliberate changes rather than implicit behavior drift.&lt;/p&gt;
&lt;p&gt;When architecture boundaries are vague, breakage tends to become runtime surprises. In DOS-era loops, compile-time certainty was a strategic advantage.&lt;/p&gt;
&lt;h2 id=&#34;state-ownership-rules&#34;&gt;State ownership rules&lt;/h2&gt;
&lt;p&gt;Global variables are tempting in small projects. They also erase accountability. Better pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each unit owns its state&lt;/li&gt;
&lt;li&gt;mutation happens through explicit procedures&lt;/li&gt;
&lt;li&gt;read-only queries are exposed as functions&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-pascal&#34; data-lang=&#34;pascal&#34;&gt;unit FrameClock;

interface
procedure Tick;
function FrameCount: LongInt;

implementation
var
  GFrameCount: LongInt;

procedure Tick;
begin
  Inc(GFrameCount);
end;

function FrameCount: LongInt;
begin
  FrameCount := GFrameCount;
end;
end.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This small discipline scales surprisingly far.&lt;/p&gt;
&lt;h2 id=&#34;circular-dependencies-are-architecture-warnings&#34;&gt;Circular dependencies are architecture warnings&lt;/h2&gt;
&lt;p&gt;If Unit A needs Unit B and B needs A, the system is signaling a design issue. In Turbo Pascal this becomes obvious quickly because cycles are painful. Use that pain as feedback:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;extract shared abstractions into Unit C&lt;/li&gt;
&lt;li&gt;invert direction of calls through callback interfaces&lt;/li&gt;
&lt;li&gt;move policy decisions up a layer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The language/tooling friction nudges you toward cleaner dependency graphs.&lt;/p&gt;
&lt;h2 id=&#34;testing-mindset-without-modern-frameworks&#34;&gt;Testing mindset without modern frameworks&lt;/h2&gt;
&lt;p&gt;Even without a test framework, you can create deterministic validation by small harness units:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fixture setup procedure&lt;/li&gt;
&lt;li&gt;operation call&lt;/li&gt;
&lt;li&gt;assertion-like result check&lt;/li&gt;
&lt;li&gt;text output summary&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key is isolating seams through interfaces. If a rendering unit can be called with prepared buffers and predictable state, manual regression checks become cheap and reliable.&lt;/p&gt;
&lt;h2 id=&#34;architecture-and-performance-are-not-enemies&#34;&gt;Architecture and performance are not enemies&lt;/h2&gt;
&lt;p&gt;Some developers fear unit boundaries will cost speed. In most DOS-scale projects, the bigger performance wins come from algorithm choice and memory locality, not from collapsing all code into one monolith. Clear units help you identify hot paths accurately and optimize where it matters.&lt;/p&gt;
&lt;p&gt;For example, keeping low-level pixel paths inside &lt;code&gt;RenderCore&lt;/code&gt; makes targeted optimization straightforward while preserving clean call sites elsewhere.&lt;/p&gt;
&lt;h2 id=&#34;cross-references-in-this-project&#34;&gt;Cross references in this project&lt;/h2&gt;
&lt;p&gt;These articles show the same pattern from different angles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/retro/dos/tp/modex/modex-part-1-planar-memory-model/&#34;&gt;Mode X Part 1: Planar Memory and Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/retro/dos/tp/modex/modex-part-4-tilemaps-and-streaming/&#34;&gt;Mode X Part 4: Tilemaps and Streaming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/retro/dos/config-sys-as-architecture/&#34;&gt;CONFIG.SYS as Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://turbovision.in6-addr.net/musings/the-cost-of-unclear-interfaces/&#34;&gt;The Cost of Unclear Interfaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Different domains, same operational truth: explicit boundaries reduce failure ambiguity.&lt;/p&gt;
&lt;h2 id=&#34;a-migration-strategy-for-messy-codebases&#34;&gt;A migration strategy for messy codebases&lt;/h2&gt;
&lt;p&gt;If you already have a tangled Pascal codebase, do not rewrite everything. Do staged extraction:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;identify one unstable subsystem&lt;/li&gt;
&lt;li&gt;define minimal interface for it&lt;/li&gt;
&lt;li&gt;move internals behind unit boundary&lt;/li&gt;
&lt;li&gt;replace direct global access with explicit calls&lt;/li&gt;
&lt;li&gt;repeat for next subsystem&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This approach keeps software running while architecture improves incrementally.&lt;/p&gt;
&lt;p&gt;Turbo Pascal units are sometimes framed as nostalgic language features. They are better understood as practical architecture tools with excellent signal-to-noise ratio. Under constraints, that ratio is everything.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
