<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://rinie.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://rinie.github.io/" rel="alternate" type="text/html" /><updated>2026-06-23T03:32:55+00:00</updated><id>https://rinie.github.io/feed.xml</id><title type="html">Rinie’s Blog</title><subtitle>Weak link willing to learn, Listen to actual Use feedback</subtitle><author><name>Rinie Kervel</name></author><entry><title type="html">Do You Trust This Document? No, I Have to Read It First.</title><link href="https://rinie.github.io/2026/06/23/wasm-sandbox-vs-policy/" rel="alternate" type="text/html" title="Do You Trust This Document? No, I Have to Read It First." /><published>2026-06-23T00:00:00+00:00</published><updated>2026-06-23T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/23/wasm-sandbox-vs-policy</id><content type="html" xml:base="https://rinie.github.io/2026/06/23/wasm-sandbox-vs-policy/"><![CDATA[<p>There are two ways to prevent untrusted code from doing something it should not.</p>

<p>The first: make it structurally impossible. The runtime defines exactly what the code can access. Memory is bounded. System calls are mediated. Network access requires explicit permission. The code literally cannot escape the boundary by design — not by instruction, not by policy, not by asking nicely. This is the WASM sandbox.</p>

<p>The second: ask the user to be careful. Send a warning. Write a policy. Train the staff. Remind people that external links may be dangerous. Hope they remember when it matters. This is “do not click on external links.”</p>

<p>One of these is engineering. One is hope.</p>

<hr />

<h2 id="the-gutenberg-boundary-and-the-semantic-instruction">The Gutenberg Boundary and the Semantic Instruction</h2>

<p>The <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic model</a> describes every system as having a physical layer and a logical layer. Security boundaries work the same way.</p>

<p>A <strong>Gutenberg security boundary</strong> is enforced at the physical execution layer. The code cannot access memory outside its allocation because the hardware MMU prevents it. The WASM module cannot write to the file system because the WASI interface does not expose that capability. The browser extension cannot read another tab’s content because the process isolation model prevents it. These boundaries hold regardless of what the code tries to do, regardless of how it was written, regardless of social engineering. The constraint is structural.</p>

<p>A <strong>Semantic security boundary</strong> is enforced at the logical instruction layer. “Do not click external links.” “Do not enable macros in documents from outside the organisation.” “Your bank will never ask for your password.” These are correct instructions. They require the user to maintain a rule in their head, apply it correctly under every circumstance, and resist social pressure, time pressure, and the ambiguity of “external” in a world where everything is connected.</p>

<p>The user is the sandbox. The user is not a reliable sandbox.</p>

<hr />

<h2 id="wasm-the-sandbox-that-holds">WASM: The Sandbox That Holds</h2>

<p>WebAssembly runs in a capability-constrained environment by design. The runtime defines a precise set of capabilities the module can use — nothing more, nothing less. Memory access is bounded to the module’s linear memory. System calls are mediated through the WASI interface and only those explicitly granted are available. Network access requires explicit host permission. File system access is scoped to specific directories if granted at all.</p>

<p>The sandbox is not a policy. It is a structural property of the execution model. The malicious WASM module that tries to read your SSH keys cannot — not because it was told not to, but because the capability was never granted and the runtime enforces the absence of capability at the Gutenberg layer.</p>

<p>When something escapes a WASM sandbox it is a CVE — a genuine implementation flaw in the runtime itself. This is rare, expensive to find, and treated as critical precisely because the entire security model depends on the boundary holding. The community responds immediately because the escape is the exception that proves the rule. The rule is that the sandbox holds structurally.</p>

<p>The cognitive tax on the user: zero. The user does not think about the WASM sandbox. They run the application. The Gutenberg layer does its job quietly, invisibly, structurally. No warnings. No policies. No “please be careful.”</p>

<hr />

<h2 id="the-policy-that-cries-wolf">The Policy That Cries Wolf</h2>

<p>The Office “this document is from the internet” warning and the IT policy “do not click external links” are Semantic instructions dressed as Gutenberg boundaries. They look like protection. They are reminders.</p>

<p>The yellow Protected View bar in Office looks like a system-level constraint. It is a policy reminder. The moment the user clicks “Enable Editing” or “Enable Content,” the document can do everything a local document can do — execute macros, phone home, access the file system within the user’s permissions. The Gutenberg layer is not constrained. The user was simply warned. The warning is the entire security model.</p>

<p>The IT policy “do not click external links” asks the user to:</p>
<ul>
  <li>Identify every link before clicking</li>
  <li>Evaluate whether it is internal or external</li>
  <li>Evaluate whether the external destination is trustworthy</li>
  <li>Resist social engineering that creates urgency, authority, or familiarity</li>
  <li>Do this correctly, every time, under every circumstance</li>
</ul>

<p>This is the maximum possible cognitive tax applied at the moment of maximum pressure — when someone is urgently asking you to verify an invoice, confirm a delivery, or reset a password. The policy was designed for the 1% dangerous case. The user has learned from the 99% benign case. The threat model calibrates toward “probably fine” because it almost always is. Until it is not.</p>

<p><strong>The warning that cried wolf</strong> makes this worse. The Office warning appears for every document downloaded from the internet — including the completely legitimate documents that constitute the overwhelming majority of office work. The VSCode “do you trust the authors?” dialog appears for every repository cloned from GitHub — including the thousands of legitimate repositories cloned daily without incident. The signal-to-noise ratio is so low that users learn to dismiss without reading. The warning exists. The warning is invisible. The Gutenberg layer is still wide open.</p>

<hr />

<h2 id="the-comparison">The Comparison</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>WASM sandbox</th>
      <th>“Don’t click links” policy</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Where the boundary lives</td>
      <td>Gutenberg layer (runtime)</td>
      <td>Semantic layer (user judgment)</td>
    </tr>
    <tr>
      <td>Enforcement</td>
      <td>Structural — cannot be bypassed</td>
      <td>Instructional — can be ignored or fooled</td>
    </tr>
    <tr>
      <td>Failure mode</td>
      <td>CVE — implementation flaw, rare</td>
      <td>Phishing click — social engineering, constant</td>
    </tr>
    <tr>
      <td>Cost of failure</td>
      <td>Patch the runtime</td>
      <td>Ransomware, credential theft, breach</td>
    </tr>
    <tr>
      <td>User cognitive tax</td>
      <td>Zero</td>
      <td>Maximum — evaluate every link</td>
    </tr>
    <tr>
      <td>Attacker’s required effort</td>
      <td>Find a runtime zero-day</td>
      <td>Send a convincing email</td>
    </tr>
  </tbody>
</table>

<p>The WASM model puts the complexity where it belongs — in the runtime, paid once, maintained by experts, improved over time. The policy model puts the complexity where it does not belong — in the user, paid on every click, degrading under pressure, failing predictably at scale.</p>

<p>The attacker who needs to find a WASM runtime zero-day faces a high technical barrier and a narrow window — the patch arrives quickly and is deployed uniformly. The attacker who needs to send a convincing email faces a low barrier and a permanent window — the policy is not patchable, the user is not uniformly trained, and the social engineering techniques improve faster than the awareness training.</p>

<hr />

<h2 id="the-correct-fix-is-always-gutenberg">The Correct Fix Is Always Gutenberg</h2>

<p>Every security improvement that has actually worked at scale moved the boundary to the Gutenberg layer:</p>

<p><strong>Process isolation</strong> — browser tabs cannot access each other’s memory because the operating system’s process boundary prevents it. Not a policy. A structural separation.</p>

<p><strong>Remote browser isolation (RBI)</strong> — the page executes in a cloud container. The user sees a pixel stream. The malware cannot reach the endpoint because the endpoint is not in contact with the page. Gutenberg separation: the execution environment and the user’s machine are physically different systems.</p>

<p><strong>Zero-trust network architecture</strong> — removes the assumption that “internal network = trusted.” Every connection requires authentication regardless of where it originates. The boundary is not the firewall perimeter (a Semantic boundary: “be careful outside”) but cryptographic identity (a Gutenberg boundary: “prove who you are for every connection”).</p>

<p><strong>Email sandboxing</strong> — links in emails are first resolved in an isolated cloud environment. The user’s browser only opens after the destination has been evaluated. The Gutenberg resolution happens before the Semantic commitment.</p>

<p>Each of these costs money and engineering. Each is more reliable than awareness training because each is structural rather than instructional. The user’s judgment is removed from the critical path — not because users are incompetent, but because structural boundaries do not have bad days, do not click under pressure, and do not calibrate toward “probably fine.”</p>

<hr />

<h2 id="the-document-warning-done-right">The Document Warning Done Right</h2>

<p>The Office “this document is from the internet” warning is the worst of both worlds: a Semantic instruction that looks like a Gutenberg boundary, shown so frequently that users click through without reading, providing no actual structural constraint.</p>

<p>The honest version would be modelled on WASM capability grants:</p>

<p><em>“This document requests the following capabilities that your policy restricts:</em></p>
<ul>
  <li><em>Execute macros: BLOCKED</em></li>
  <li><em>Access external network resources: BLOCKED</em></li>
  <li><em>Read files outside the document: BLOCKED</em></li>
</ul>

<p><em>The document has been opened with these capabilities disabled. To enable specific capabilities, contact IT with reference [ID].”</em></p>

<p>Specific. Enumerable. Requiring explicit approval for each capability rather than a single “Enable Content” button that grants everything. The user sees exactly what is being prevented — the Gutenberg constraints made visible rather than hidden behind a yellow bar that says “be careful.”</p>

<p>This is the <a href="https://rinie.github.io/2026/06/08/hiding-the-waterline/">waterline made visible</a> applied to security. Not hiding the constraint. Not pretending the constraint is stronger than it is. Showing exactly where the Gutenberg boundary is and what it is preventing.</p>

<hr />

<h2 id="auto-mode-and-the-real-risk">Auto Mode and the Real Risk</h2>

<p>The real risk in WASM is the sandbox escape — a zero-day that breaks the Gutenberg boundary. This is the scenario that the WASM security community works hardest to prevent and responds to most urgently when it occurs. The entire value of the model depends on the structural guarantee holding. When it fails, the failure is visible, attributable, and patchable.</p>

<p>The real risk in “do not click links” is different: the policy degrades continuously, invisibly, without any visible failure event. No CVE is filed when a user clicks a phishing link. The policy failure is distributed across thousands of individual decisions, each one invisible, each one accumulating into the breach that eventually becomes visible. By then it is too late and the breach cannot be attributed to any single policy failure.</p>

<p>The WASM escape is dramatic and rare. The policy failure is quiet and constant. The security model that produces dramatic rare failures is more manageable than the one that produces quiet constant ones — because dramatic rare failures get patched.</p>

<p>Quiet constant failures get awareness training.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/05/26/boundary-lifecycle/">The Boundary Has a Lifecycle</a> on WASM as the endpoint of boundary evolution, <a href="https://rinie.github.io/2026/06/22/ambiguity-is-not-a-bug/">Ambiguity Is Not a Bug</a> on the resolver that honestly surfaces uncertainty, and <a href="https://rinie.github.io/2026/06/08/hiding-the-waterline/">Hiding the Waterline Makes You Drown Without Knowing Why</a> on the cost of invisible boundaries.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="gutenberg-semantic" /><category term="wasm" /><category term="security" /><category term="trust" /><category term="sandbox" /><category term="boundary" /><summary type="html"><![CDATA[The WASM sandbox puts the security boundary in the Gutenberg layer where it can be enforced structurally. The 'do not click external links' policy puts it in the Semantic layer — the user's judgment — where it degrades under pressure and fails predictably at scale. One is engineering. One is hope.]]></summary></entry><entry><title type="html">Ambiguity Is Not a Bug: Trust, Provenance, and the Resolver That Cried Wolf</title><link href="https://rinie.github.io/2026/06/22/ambiguity-is-not-a-bug/" rel="alternate" type="text/html" title="Ambiguity Is Not a Bug: Trust, Provenance, and the Resolver That Cried Wolf" /><published>2026-06-22T00:00:00+00:00</published><updated>2026-06-22T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/22/ambiguity-is-not-a-bug</id><content type="html" xml:base="https://rinie.github.io/2026/06/22/ambiguity-is-not-a-bug/"><![CDATA[<p>Your contact list shows “Mrs Kervel” calling. You answer. It is a stranger — Mrs Kervel sold her old SIM six months ago. The resolver (your contacts app) presented confident Semantic identity over a Gutenberg identifier that no longer mapped to the person you knew. The confidence was false. The ambiguity was real. Nobody told you.</p>

<p>This is not a security failure. It is a resolver design failure. The system that should have shown “Mrs Kervel (number may have changed)” showed “Mrs Kervel” and let you be taken for a ride.</p>

<p>Ambiguity is a fact of life in any distributed system where Gutenberg identifiers (numbers, addresses, package names, domain names) and Semantic identities (people, organisations, software) evolve independently. The resolver that hides that ambiguity behind confident presentation does not make the system safer. It moves the risk from the resolver to the user — without telling the user the risk was moved.</p>

<hr />

<h2 id="the-whatsapp-new-number-fraud">The WhatsApp New Number Fraud</h2>

<p>“Hey it’s me, I got a new number, save it.”</p>

<p>The message arrives from an unknown number. The claim is Semantic — it’s me, a person you know. The Gutenberg identifier is new, unlinked to any prior trust relationship, with no verified connection to the person claimed.</p>

<p>The fraud works because messaging apps present Semantic identity over unverified Gutenberg identifiers. The new number has no history in your contacts. The contact app shows no connection. The messaging app shows no warning. The user is left to evaluate a bare Semantic claim with no Gutenberg signal to check it against.</p>

<p><strong>The Use-Pull fix that would actually work:</strong></p>

<p>A new number claiming a known identity could trigger a confidence signal rather than a forced choice. Not “this is suspicious, block it” — that would generate false positives for everyone who genuinely changed phones. Not “trust it” — that is the current broken default. But: “new number, no prior contact history — the claimed identity is unverified.”</p>

<p>Better still: <strong>location context as a soft signal.</strong> A new number from the same country, same carrier prefix, same rough geography as the existing contact record is more likely to be a genuine change. A new number from a different country, a VOIP prefix, or a geography inconsistent with the contact’s history is worth flagging — not blocking, not rejecting, but flagging with visible ambiguity. “Hey it’s me — but this number is registered in a different country than your contact. Verify before trusting.”</p>

<p>This is more useful than “your bank never calls you.” That instruction asks the user to maintain a rule in their head at the moment of highest social pressure — when someone is on the line claiming urgency, claiming authority, claiming to be someone trusted. The cognitive tax is maximum precisely when the fraud is most likely. The resolver that surfaces the Gutenberg anomaly (new number, foreign prefix, geography mismatch) removes the cognitive tax from the moment of pressure and puts it where it belongs — in the system that has the data.</p>

<hr />

<h2 id="sms-links-and-qr-codes-the-unvalidatable-url">SMS Links and QR Codes: The Unvalidatable URL</h2>

<p>The browser does something important with URLs that SMS and QR codes do not: it shows you where you are going before you commit.</p>

<p>A link in a browser is inspectable. Hover over it and the status bar shows the destination. The URL is visible. The domain can be checked. The HTTPS padlock can be verified. The browser’s Gutenberg layer (the URL) is exposed to the user’s Semantic layer (their judgment about whether to trust it) before the navigation happens.</p>

<p>An SMS link is not inspectable in the same way. The display text can say “click here to confirm your delivery” while the URL resolves to <code class="language-plaintext highlighter-rouge">parcel-track-nl-confirm.suspicious.ru</code>. The Semantic layer (delivery confirmation) and the Gutenberg layer (the actual destination) are deliberately decoupled. The user sees the Semantic claim without the Gutenberg evidence.</p>

<p>A QR code is worse — the Gutenberg layer (the URL encoded in the squares) is completely invisible until scanned. The user commits to the resolution before they can evaluate it. The QR code is a deliberate opacity layer between the Semantic intent (“scan to pay”) and the Gutenberg destination (“your payment goes here”).</p>

<p><strong>The stable destination problem:</strong></p>

<p>Even when the URL is visible, SMS links and QR codes often use URL shorteners — <code class="language-plaintext highlighter-rouge">bit.ly/xyz123</code>, <code class="language-plaintext highlighter-rouge">t.co/abcdef</code> — which hide the final destination behind a redirect. The short URL is stable. The destination is not. A QR code printed on a restaurant menu in 2023 that pointed to the menu PDF still points to the same short URL in 2026 — but the short URL may have been reconfigured to point somewhere else. The Gutenberg identifier (the QR code, the short URL) appears stable. The Semantic destination has moved. The resolver presents no ambiguity.</p>

<p>The browser’s URL bar is the waterline made visible. It shows you the Gutenberg address you are about to cross to. SMS links and QR codes hide the waterline. The user is taken to a destination they could not evaluate before arriving.</p>

<p><strong>The Use-Pull fix:</strong> show the resolved URL before navigation. QR code scanners that preview the destination URL before opening it — several exist, none are default. SMS apps that expand short URLs and show the final destination on hover. The Gutenberg layer made visible before commitment, not after. The waterline shown, not hidden.</p>

<hr />

<h2 id="the-npm-hijack-when-the-package-name-stays-stable">The npm Hijack: When the Package Name Stays Stable</h2>

<p>The npm supply chain attack exploits the same resolver gap at the software layer.</p>

<p>A package name (<code class="language-plaintext highlighter-rouge">left-pad</code>, <code class="language-plaintext highlighter-rouge">event-stream</code>, <code class="language-plaintext highlighter-rouge">colors</code>) is a Semantic identifier. The specific version of code in the registry is the Gutenberg artifact. The resolver (npm) maps the name to the current version and presents the result confidently. <code class="language-plaintext highlighter-rouge">npm install colors</code> — here is colors.</p>

<p>The attack: the maintainer transfers the package to a new owner, or publishes a new version, or the account is compromised. The Semantic name is stable. The Gutenberg artifact it resolves to has changed. The resolver shows no ambiguity. The developer’s <code class="language-plaintext highlighter-rouge">package.json</code> says <code class="language-plaintext highlighter-rouge">colors</code> — they get whatever <code class="language-plaintext highlighter-rouge">colors</code> currently is, not what <code class="language-plaintext highlighter-rouge">colors</code> was when they last verified it.</p>

<p><strong>The 72-hour window:</strong></p>

<p>Most supply chain attacks become detectable within 72 hours — someone notices the behaviour change, the registry flags the version, the security community alerts. But in those 72 hours every <code class="language-plaintext highlighter-rouge">npm install</code> resolves the compromised package with full confidence. The resolver’s job — map name to artifact — is technically correct. The artifact changed. The confidence is false.</p>

<p><strong>The DNS version chain analogy:</strong></p>

<p>The correct fix is the DNS versioning idea from <a href="https://rinie.github.io/2026/05/28/why-ipv6-def-push-failed/">earlier in the series</a>: a signed monotonic version chain where the resolver can show “this is the current version AND this is the last known-good version AND here is how long ago it changed.” Not forcing a choice — surfacing the ambiguity.</p>

<p><code class="language-plaintext highlighter-rouge">npm install colors</code> with a 3-day-old maintainer transfer could show: “⚠ This package changed maintainers 3 days ago. Last verified version: 1.4.0. Current version: 1.4.1. Do you want to review the diff before installing?”</p>

<p>Not blocking. Not forcing. Surfacing. The user drives. The resolver shows the map.</p>

<hr />

<h2 id="the-warning-that-cried-wolf">The Warning That Cried Wolf</h2>

<p>The Office “this document is from the internet” warning and VSCode’s “do you trust the authors of this folder?” are attempts to surface provenance ambiguity. Technically correct. Practically invisible.</p>

<p>They are shown so frequently for benign cases — every document downloaded from a legitimate source, every repository cloned from GitHub — that users click through them reflexively. The Gutenberg signal (provenance uncertain) is present. The Semantic signal (this specific thing may be dangerous) is absent. The warning cannot distinguish between “benign download from trusted source” and “compromised package from hijacked account.” Both get the same dialog. Users learn to dismiss both.</p>

<p>This is the resolver crying wolf. The warning system that treats all ambiguity as equally concerning produces users who treat all warnings as equally ignorable. The cognitive tax of reading and evaluating every warning exceeds the cognitive budget of most users doing routine work. The warning becomes noise. The ambiguity it was meant to surface is hidden again — not by false confidence but by warning fatigue.</p>

<p><strong>The Use-Pull fix:</strong> calibrated signals, not binary alerts.</p>

<ul>
  <li>✓ <strong>Known good</strong> — previously verified, no changes since, consistent provenance</li>
  <li>ℹ <strong>Routine</strong> — from internet but consistent with expected source, no anomalies</li>
  <li>⚠ <strong>Changed recently</strong> — maintainer transfer, new certificate, geography mismatch</li>
  <li>🚨 <strong>Anomaly</strong> — significant departure from established pattern, verify before proceeding</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">⚠</code> and <code class="language-plaintext highlighter-rouge">🚨</code> states earn attention because the <code class="language-plaintext highlighter-rouge">✓</code> and <code class="language-plaintext highlighter-rouge">ℹ</code> states are quiet. The resolver that shows confidence levels rather than binary safe/unsafe gives the user a calibrated map rather than a constant alarm.</p>

<hr />

<h2 id="the-ai-training-cutoff-stale-certainty">The AI Training Cutoff: Stale Certainty</h2>

<p>The same pattern appears in AI assistants. The training cutoff is a Gutenberg fact — the model’s knowledge ends at a specific date. The answers are presented at a Semantic confidence level that does not reflect the Gutenberg staleness.</p>

<p>Ask about a DNS configuration that changed last week. Ask about a package that was compromised three days ago. Ask about a number portability rule that changed last month. The model answers from its last known state — confidently, helpfully, incorrectly. The Gutenberg state (what is true now) diverged from the Semantic confidence (what the model believes). The resolver showed no ambiguity.</p>

<p>The Use-Pull response: surface the uncertainty. “As of my training data, X — but this type of information changes frequently and may have been updated since.” Not refusing to answer. Not pretending certainty. Showing the confidence level alongside the answer so the user can calibrate.</p>

<p>The 72-hour supply chain attack window, the DNS propagation delay, the AI training cutoff, the QR code pointing to a stale destination — all the same structural problem. Gutenberg state is ephemeral. Semantic identity claims to be stable. The gap between them is where the fraud lives, where the hijack happens, where the stale answer misleads.</p>

<hr />

<h2 id="the-resolver-that-serves-the-user">The Resolver That Serves the User</h2>

<p>The common thread in every case is the same: the resolver that presents confident results when the underlying data is ambiguous, stale, or unverified is not serving the user. It is serving its own appearance of competence.</p>

<p>The honest resolver:</p>
<ul>
  <li>Shows confidence levels, not just results</li>
  <li>Flags recent changes, maintainer transfers, geography mismatches, staleness</li>
  <li>Does not force merges or choices — shows the ambiguous state and lets the user decide</li>
  <li>Treats “I’m not sure” as a valid answer, not a failure state</li>
  <li>Reserves strong warnings for genuine anomalies so they are actually read</li>
</ul>

<p>The WhatsApp fraud, the npm hijack, the DNS propagation gap, the QR code pointing somewhere unexpected, the AI training cutoff, the Office warning nobody reads — all resolvable not by eliminating ambiguity (you cannot) but by representing it honestly.</p>

<p>The user should drive. The resolver shows the map. When the map has a question mark on it, the map should show the question mark — not fill it in with the most confident-looking answer available and hope nobody notices.</p>

<p>Ambiguity is not a bug. Hiding it is.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/05/27/uuids-are-not-names/">UUIDs Are Not Names</a> on the Mum/Mrs Kervel many-to-one problem, <a href="https://rinie.github.io/2026/05/28/why-ipv6-def-push-failed/">Why IPv6’s Def-Push Failed</a> on load-bearing boundaries, and <a href="https://rinie.github.io/2026/06/08/hiding-the-waterline/">Hiding the Waterline Makes You Drown Without Knowing Why</a> on the cost of invisible boundaries.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="gutenberg-semantic" /><category term="resolver" /><category term="trust" /><category term="security" /><category term="ambiguity" /><category term="npm" /><category term="dns" /><summary type="html"><![CDATA[The resolver that presents false certainty is more dangerous than the resolver that honestly says 'I'm not sure.' WhatsApp fraud, npm hijacking, DNS propagation gaps, QR codes, SMS links — all the same problem: the Gutenberg state changed, the Semantic layer did not update, and the resolver showed no ambiguity. The user was taken for a ride.]]></summary></entry><entry><title type="html">Muddy Water(line)s, Shady User Experience</title><link href="https://rinie.github.io/2026/06/21/muddy-waterlines-sux/" rel="alternate" type="text/html" title="Muddy Water(line)s, Shady User Experience" /><published>2026-06-21T00:00:00+00:00</published><updated>2026-06-21T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/21/muddy-waterlines-sux</id><content type="html" xml:base="https://rinie.github.io/2026/06/21/muddy-waterlines-sux/"><![CDATA[<p>Muddy Waters sang about power imbalance — the authentic signal buried under noise, people held down by systems they did not choose, the thing you needed to hear getting drowned by the thing someone else wanted you to hear.</p>

<p>He was singing about the blues. He was also, without knowing it, singing about dark patterns, cookie banners, and the browser that became the server spy.</p>

<p>The <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic model</a> describes two layers in every information system: the physical layer (bytes, addresses, infrastructure) and the logical layer (meaning, names, content). The waterline between them is where translation happens. When the waterline is clean and visible, users can navigate — they know which layer they are in, what each element means, and how to get to their goal. When the waterline is muddy, navigation fails. The user cannot tell what they are looking at, what it will do, or how to get out.</p>

<p>SUX: Shady User Experience.</p>

<hr />

<h2 id="two-kinds-of-muddy">Two Kinds of Muddy</h2>

<p>Not all muddy waterlines are the same. The distinction matters because the fix is different.</p>

<p><strong>Accidentally muddy</strong> — the ORM that hides the SQL without meaning to. The legacy system that grew organically until nobody understood it. The architect who collapsed the waterline through ignorance rather than intent. The failure is structural. The cause is proximity blindness or accumulated technical debt. The fix: go to the Gemba, find the sticky notes, clean the waterline.</p>

<p><strong>Deliberately muddy</strong> — the cookie banner designed to make “reject all” impossible to find. The airline booking flow that reveals fees one screen at a time until cancelling costs more than continuing. The insurance policy with the exclusions in 6-point font. The newsletter modal that blocks the content until dismissed and whose close button is 8 pixels in the corner. The failure is intentional. The cause is a business decision that the user’s confusion is profitable. The fix: regulation, competition, and naming it clearly.</p>

<p>The Shady User Experience is always deliberate. The muddiness is not a side effect — it is the mechanism. The boundary between what the user was told and what actually happens is kept muddy because clarity would reveal a trade the user would not accept.</p>

<hr />

<h2 id="the-dark-pattern-catalogue">The Dark Pattern Catalogue</h2>

<p><strong>The cookie banner.</strong> GDPR was designed to give users meaningful control over their data. The correct implementation: a simple choice, equal prominence for accept and reject, no dark patterns. The actual implementation, on most sites: a large green Accept button, a small grey Manage Preferences link that opens a second screen with 400 toggles all set to on, no “reject all” button on the first screen, and a design explicitly crafted to maximise consent rates. The regulation was correct. The implementation was captured by the Def-Push tribe and turned into noise. The waterline between “you have control” and “you will click accept” was muddied deliberately.</p>

<p><strong>The disappearing close button.</strong> The chatbot appears in the corner. The user does not want it. There is no clean close. There is a minimise that makes it smaller. There is an X that opens a feedback dialog before dismissing. The clean exit was removed because the Def decided the user should see the chatbot whether they wanted to or not. The cognitive tax is deliberate. The muddiness is the feature.</p>

<p><strong>The exit intent popup.</strong> The cursor moves toward the browser chrome. A modal appears. The site is now intercepting the user’s attempt to leave — using JavaScript to detect the intent to close the tab and inserting a Def message before the user can act. The semantic intent (leave this page) is intercepted at the Gutenberg layer (cursor position, mouse trajectory) and redirected. The user’s agent has been subverted by the server.</p>

<p><strong>The roach motel.</strong> Signing up is one click. Cancelling requires finding the account page, then the subscription tab, then the cancellation flow, then the retention screen offering discounts, then the confirmation screen, then a follow-up email offering to pause instead. Each step was designed. The asymmetry between entry and exit is not an oversight — it is the product of someone’s sprint ticket: reduce churn by adding friction to the cancellation flow. The Def optimised for the Def’s metrics. The Use paid the cognitive tax.</p>

<p><strong>The forced account.</strong> You want to buy one thing. The checkout requires creating an account. The account requires an email address and a password. The email address will be used for marketing. The password will be stored in a database that may be breached. You wanted to buy a lamp. The Def wanted a CRM record. The waterline between “purchase” and “data collection” was muddied so you would not notice the trade you were making.</p>

<hr />

<h2 id="the-browser-arms-race">The Browser Arms Race</h2>

<p>The browser’s formal name in the HTTP specification is the <strong>user agent</strong> — the software that acts on behalf of the user at the Gutenberg layer. It represents the user’s interests. It renders what the server provides. What the user does with that content is the user’s domain.</p>

<p>When sites began subverting the user’s experience — popup windows, popunders, right-click disables, exit intent scripts — the browser vendors responded on behalf of their users. Popup blockers. Gesture requirements for notification requests. Mixed content blocking. Each protection was Use-Pull: the browser vendor listening to the Use signal (users being harmed) and acting on it.</p>

<p>The arms race:</p>

<ol>
  <li>Sites spawn popup windows without user intent</li>
  <li>Browsers add popup blockers</li>
  <li>Sites move to popunders — windows that open behind the current one</li>
  <li>Browsers block popunders</li>
  <li>Sites move to exit intent overlays — same manipulation, inside the page</li>
  <li>Browser vendors cannot block what happens inside the page without breaking legitimate use</li>
</ol>

<p>At each step the browser vendor acted for the user. The server kept finding workarounds. The user agent tried to stay on the user’s side.</p>

<p><strong>Right-click disable</strong> is the micro-example of where the server reaches through the Gutenberg layer to suppress the Semantic tools the browser provides. <code class="language-plaintext highlighter-rouge">oncontextmenu="return false"</code> overrides the context menu — the boundary marker that exposes what the browser knows about the element and offers semantic operations on it. It does not work for determined users (the image is still in the cache, the source is still accessible). It breaks accessibility and legitimate use. It signals that the site knows its content would not survive inspection.</p>

<p>The browser is the user agent. Not the server’s enforcement mechanism. When sites disable right-click, they are not protecting their content — they are muddying the waterline between what you can see and what you can do with it.</p>

<hr />

<h2 id="chrome-another-user-agent-corrupted-into-a-big-tech-spy">Chrome: Another User Agent Corrupted into a Big Tech Spy?</h2>

<p>The question mark is doing real work. Chrome still does many things that genuinely serve users. But the direction is clear and the mechanism is visible.</p>

<p><strong>Corrupted</strong> is the precise word. Not broken. Not incompetent. Corrupted — the original purpose deliberately subverted by a conflicting interest while the vocabulary of the original purpose is retained to mask the subversion.</p>

<p>Chrome launched in 2008 as a genuinely better browser. Faster, cleaner, more standards-compliant than IE. The V8 engine improved JavaScript performance for everyone. Process isolation improved security. Google’s interests (more web usage = more searches = more ad revenue) aligned with the user’s interests (a better browser). The user agent acted for the user.</p>

<p>Then the interests diverged. Chrome’s market share grew to ~65% dominance. Switching costs accumulated. Google became simultaneously the browser vendor, the largest digital advertising company, the dominant search engine, and the owner of YouTube. Every genuine privacy improvement that served users cost Google advertising revenue.</p>

<p><strong>Manifest V3</strong> was announced as a security improvement. The practical effect: ad blockers became less effective. The <code class="language-plaintext highlighter-rouge">webRequestBlocking</code> API that allowed ad blockers to intercept and block requests dynamically was deprecated. The replacement <code class="language-plaintext highlighter-rouge">declarativeNetRequest</code> API uses pre-declared rules — significantly less capable against dynamic ad injection and the tracking techniques that matter most for privacy.</p>

<p>A genuine user agent would strengthen ad blocking — hundreds of millions of users install ad blockers because they want them. Chrome weakened ad blocking. Google’s revenue requires ads to be delivered and measured. The sequence is not ambiguous.</p>

<p><strong>The Privacy Sandbox and the Topics API</strong> complete the inversion. Third-party cookies (cross-site tracking via the server) are being replaced by the Topics API — the browser watches what you read, categorises your interests, and reports them to advertisers on request. The tracking moves from the server into the user agent. The browser is now the spy. The data never leaves the browser — technically. The surveillance profile is still built. The targeting still happens. The cheerfulness of “we’re building a more private web” continues.</p>

<p><strong>The Firefox and Safari contrast:</strong></p>

<p>Mozilla kept <code class="language-plaintext highlighter-rouge">webRequestBlocking</code>. Mozilla has no advertising business. uBlock Origin works fully on Firefox — because there was no business reason to weaken it. Apple’s Intelligent Tracking Prevention is genuine — Apple’s revenue is hardware and services, not ad targeting. The user agent with no advertising conflict acts for the user. The user agent with the advertising conflict acts for the conflict.</p>

<p>The browser you choose is a Def-Push / Use-Pull decision. Chrome’s Def is now shaped by Google’s advertising business. Firefox’s Def is shaped by users and a non-profit mission. The browser that actually represents you is the one whose business model aligns with your interests — not the advertiser’s.</p>

<p>Chrome is now both the user agent and the server spy. That is the muddy waterline at its muddiest — the software that is supposed to represent you, representing someone else, while telling you it is still on your side.</p>

<hr />

<h2 id="the-regulatory-response-and-its-limits">The Regulatory Response and Its Limits</h2>

<p>When the waterline is deliberately muddy, regulation is the only corrective mechanism — because the market rewards the muddying and punishes clarity. Higher conversion rates, lower cancellation rates, more data collected: the Def’s metrics improve when the waterline is muddier. The Use signal (user frustration, distrust, abandonment) is diffuse, delayed, and hard to attribute.</p>

<p>GDPR was the attempt to mandate a clean waterline between your data and their data. The regulation was correct in principle. The implementation was captured: the cookie banner industry exists to produce technically compliant banners that maximise consent while minimising genuine user understanding. The regulation added a layer of noise without delivering the benefit. The waterline got muddier.</p>

<p>The correct regulatory target is not the specific dark pattern but the waterline itself: the boundary between what the user was told and what actually happens must be visible, accessible, and honest. Not “you clicked accept on a 47-toggle preference screen” — that is a muddy waterline laundered through compliance theatre. The user’s informed consent is the Semantic layer. The consent mechanism is the Gutenberg layer. The two must be honestly connected.</p>

<hr />

<h2 id="muddy-waters-knew">Muddy Waters Knew</h2>

<p>The authentic signal — what the user actually wants, what the content actually is, what the system actually does — is not hard to find. It is buried. Deliberately, systematically, profitably buried under cookie banners and exit popups and Terms of Service agreements and mandatory account creation flows and Manifest V3 API changes that weaken ad blockers.</p>

<p>Muddy Waters sang about the same structural problem. Power held by those who control the infrastructure. The authentic signal — the music, the voice, the thing that needed to be heard — getting buried under the noise of those who controlled the pressing plants, the radio stations, the distribution networks. The Use side producing genuine signal. The Def side muddying it for profit.</p>

<p>The fix is the same in both cases: name it, clean it, and where cleaning requires forcing someone to give up a profitable muddying, legislate it.</p>

<p>The browser is the user agent. Not the server spy. The waterline between what you are shown and what is actually happening should be visible, accessible, and honest.</p>

<p>That is not a technical requirement. It is a basic standard of dealing with people fairly.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/06/08/hiding-the-waterline/">Hiding the Waterline Makes You Drown Without Knowing Why</a> on the cost of invisible boundaries, <a href="https://rinie.github.io/2026/06/16/complaint-department-transferred/">The Complaint Department Has Been Transferred to Another Dimension</a> on enshittification and closed feedback loops, and <a href="https://rinie.github.io/2026/05/29/competition-use-pull-monopoly-def-push/">Competition Is Use-Pull. Monopoly Is Def-Push. Government Is Both.</a> on why regulation is sometimes the only fix.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="gutenberg-semantic" /><category term="waterline" /><category term="dark-patterns" /><category term="ux" /><category term="browser" /><category term="chrome" /><category term="privacy" /><summary type="html"><![CDATA[Muddy Waters sang about power imbalance and the authentic signal buried under noise. Muddy waterlines are the same pattern in software: the Gutenberg/Semantic boundary obscured deliberately so the Use side cannot navigate. The disappearing close button. The cookie banner designed to confuse. Chrome: the user agent that became the server spy.]]></summary></entry><entry><title type="html">Nothing Is Confusing to Me: The Inmates Are Running the Asylum</title><link href="https://rinie.github.io/2026/06/20/nothing-is-confusing-to-me/" rel="alternate" type="text/html" title="Nothing Is Confusing to Me: The Inmates Are Running the Asylum" /><published>2026-06-20T00:00:00+00:00</published><updated>2026-06-20T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/20/nothing-is-confusing-to-me</id><content type="html" xml:base="https://rinie.github.io/2026/06/20/nothing-is-confusing-to-me/"><![CDATA[<p>In the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic model</a> the semantic layer has two sides. The <strong>Def side</strong> — the producers, the architects, the engineers, the people who built the system and know it completely. The <strong>Use side</strong> — the users, the clients, the people the system is supposed to serve.</p>

<p>The problem named by Alan Cooper in his 1999 book <em>The Inmates Are Running the Asylum</em> is not that the Def side is malicious. It is that proximity to the Def makes the Use side invisible. The people closest to the system are the worst possible designers of its interface — not because they are incompetent but because nothing is confusing to them.</p>

<p>The programmer who wrote the error message that says <code class="language-plaintext highlighter-rouge">NullPointerException</code> was not trying to confuse anyone. They just never considered that the user is not them. The developer who designed the 47-step installation wizard thought they were being thorough. The engineer who put twelve options in a dropdown thought they were being comprehensive. The UI that made perfect sense to the person who built it is the UI that sends support tickets from everyone else.</p>

<hr />

<h2 id="proximity-creates-blindness">Proximity Creates Blindness</h2>

<p>Cooper’s insight is precise: the mental model of the person who built the system is so complete, so internalised, so automatic, that gaps in the interface are invisible to them. They cannot see what is confusing because nothing is confusing. The path through the interface that confuses every new user is transparent to the engineer who designed it — they know where the button is, they know what the error means, they know which menu contains the option. They have always known. They cannot unknow it.</p>

<p>This is distinct from the failure named in the <a href="https://rinie.github.io/2026/06/19/where-is-the-close-button/">previous post</a> — the designer who knew about usability but chose brand over user. The inmates are not making a choice. They are experiencing a genuine inability to see from the user’s perspective. The failure is not arrogance. It is the natural consequence of expertise.</p>

<p>The expert skier cannot remember what it felt like to not know how to turn. The expert programmer cannot remember what it felt like to not know what a null pointer is. The expertise is real and valuable. The blindness is its shadow.</p>

<hr />

<h2 id="the-two-steves-and-the-feedback-threshold">The Two Steves and the Feedback Threshold</h2>

<p>A Dancing Bear is a feature that impresses in a demo but serves nobody in daily use. The bear that dances is impressive. The bear that dances is not useful. The difference between engineers who produce usable interfaces and engineers who produce confusing ones is not intelligence or care. It is the feedback threshold — how loud the Use signal has to be before it reaches the Def. And how early the Dancing Bears get spotted.</p>

<p><strong>Steve Wozniak</strong> had a low threshold. He went to the Homebrew Computer Club. He watched hobbyists use his machines. He asked questions. He listened before the design was locked in. The Use signal arrived early and cheaply — a conversation, an observation, a question from someone who was confused. The Apple II had expansion slots because Woz heard “I want to connect things to this” before the case was closed.</p>

<p>Woz was not immune to Dancing Bears. He genuinely believed the Segway would conquer the world. Invested in it. Rode one everywhere. The Use signal (people finding it embarrassing in public, cities banning it from pavements, the price making it inaccessible) was there. For once his threshold was higher than usual. The Segway did not conquer the world. It became a vehicle for mall security guards and tourist groups.</p>

<p>Mostly harmless. Woz was not a jerk about the Segway. He did not impose it on anyone. He believed in a thing that did not work out, moved on, remained delighted by technology. The error was proportional. The humility remained. The threshold recalibrated.</p>

<p><strong>Steve Jobs</strong> killed the Dancing Bears of engineers ruthlessly — every feature that added complexity without serving the user in daily use was cut. No feature creep. No “but it’s technically impressive.” If it did not serve the person holding the phone, it was gone. His threshold for engineering Dancing Bears was remarkably low.</p>

<p>But he was blind to the Dancing Bears of designers — the features that looked beautiful in a presentation, that impressed in a keynote, that made reviewers gasp, but that created daily friction for the person living with the product. The butterfly keyboard danced beautifully on stage. The single-port MacBook was a design statement. The Mac Pro trash can was stunning in a photo. All Dancing Bears. All imposing daily cognitive tax on the users who actually lived with them.</p>

<p>The distinction is precise:</p>
<ul>
  <li><strong>Engineering Dancing Bears</strong> — technically impressive, nobody asked for it, adds complexity. Jobs saw these clearly and cut them.</li>
  <li><strong>Design Dancing Bears</strong> — visually impressive, makes great keynote material, creates daily friction. Jobs could not see these because they were his tribe’s output.</li>
</ul>

<p>Jobs had a high threshold for designer Dancing Bears because the designers were his tribe. The feedback that the butterfly keyboard was unreliable had to become a PR crisis before it broke through. Not because he did not care about users — because the aesthetic conviction was load-bearing. Admitting the keyboard was wrong meant admitting the statement it made was wrong.</p>

<p><strong>Jony Ive</strong> had a high threshold shaped by the same aesthetic conviction. The butterfly keyboard produced genuine user suffering for years before the feedback broke through. The threshold was set by the identity investment, not by indifference.</p>

<p>The inmates have threshold zero — no feedback reaches the designer because they cannot see the confusion. Not because they have stopped caring. Because proximity has made the confusion invisible.</p>

<p><strong>The calibrated threshold — the Woz/Krug position:</strong> low enough that small friction is worth investigating, high enough that every random opinion does not derail the design. The weak link willing to learn. The designer who asks “what did I miss?” when a user hesitates, rather than “why does the user not understand this?”</p>

<hr />

<h2 id="carplay-and-android-auto-the-phone-knows-the-user">CarPlay and Android Auto: The Phone Knows the User</h2>

<p>CarPlay and Android Auto exist because the native car infotainment systems were built by automotive engineers designing for automotive engineers. The menu structures mirrored the engineering team’s internal taxonomy. Features were buried three levels deep because that was how the software was architected. Error messages described the system state rather than the driver’s situation.</p>

<p>The inmates were running the in-car interface. The result was systems so confusing that drivers were looking away from the road for dangerous durations trying to find basic controls.</p>

<p>CarPlay and Android Auto are Apple and Google saying: we have watched users struggle with interfaces, we know how to design for touch and glance, let us put our semantic layer over your Gutenberg hardware. And there is an underrated side effect: the infotainment system in a five-year-old car gets more capable every time the driver buys a new phone. The car’s Gutenberg layer stays put; the semantic layer upgrades in the driver’s pocket. The seam held.</p>

<hr />

<h2 id="all-inmates-are-equal-some-are-more-equal-than-others">All Inmates Are Equal. Some Are More Equal Than Others.</h2>

<p>Orwell’s line from Animal Farm applies precisely. The revolution starts to serve everyone. The pigs end up running the farm for themselves. Each generation more convinced their model is correct. The Use signal — the hungry animals, the confused users, the driver looking away from the road — reframed as a management problem rather than a design failure.</p>

<p>The inmates who learn from feedback become less equal over time. They drift toward the users, away from the Def. Each piece of friction they witness recalibrates their threshold a little lower. The expertise remains. The blindness recedes.</p>

<p>The inmates who persist become more equal — more convinced, higher threshold, more insulated from the Use signal that would correct them. The mental model hardens. The interface stops changing. The support tickets accumulate.</p>

<p>The fix is not smarter engineers. The fix is exposure — real users, real confusion, watched in real time without helping. The Gemba walk for interface design: sit with someone who has never used the system, watch them use it without intervening, note every hesitation, every wrong tap, every “where is the close button?” The five hours of watching three users fail is worth more than three months of internal design review.</p>

<p>Not because three users are statistically significant. Because watching someone hesitate once, out loud, in front of you, destroys the confident assumption that the interface is obvious. The threshold recalibrates. The blindness lifts a little.</p>

<p><strong>Learn from feedback or persist as an inmate.</strong> That is the choice. Not a moral choice — a design one. The interface that keeps confusing users is the one whose designers never watched a user be confused.</p>

<p>The user does not hold it the wrong way. The designer who thinks they do has stopped learning.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a> and the UX trilogy. Related: <a href="https://rinie.github.io/2026/06/19/where-is-the-close-button/">Every ‘Where Is the Close Button?’ Is a Bug</a> on Krug’s principle and the cognitive tax, <a href="https://rinie.github.io/2026/06/17/going-to-the-gemba/">Going to the Gemba</a> on watching the Use signal where it lives, and <a href="https://rinie.github.io/2026/06/21/muddy-waterlines-sux/">Muddy Water(line)s, Shady User Experience</a> on when the interface is wrong by design rather than by blindness.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="ux" /><category term="def-push" /><category term="use-pull" /><category term="cooper" /><category term="proximity-blindness" /><category term="interface" /><summary type="html"><![CDATA[Alan Cooper's 'The Inmates Are Running the Asylum' names the failure mode precisely: the engineers who built the software are now designing the interface. Not malicious. Genuinely blind to the gap between their own mental model and the user's. Proximity creates blindness. The fix is not smarter engineers — it is exposure to actual users.]]></summary></entry><entry><title type="html">Every ‘Where Is the Close Button?’ Is a Bug</title><link href="https://rinie.github.io/2026/06/19/where-is-the-close-button/" rel="alternate" type="text/html" title="Every ‘Where Is the Close Button?’ Is a Bug" /><published>2026-06-19T00:00:00+00:00</published><updated>2026-06-19T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/19/where-is-the-close-button</id><content type="html" xml:base="https://rinie.github.io/2026/06/19/where-is-the-close-button/"><![CDATA[<p>In 2000, Steve Krug published a book called “Don’t Make Me Think.” The title is the argument. The interface that works is the one that requires no thought — not because it is simple but because it has absorbed all the complexity that would otherwise land on the user.</p>

<p>Every “where is the close button?” is a bug.
Every “wait, how do I get back?” is a bug.
Every “I didn’t mean to click that” is a bug.
Every animation that delays the action the user wanted to take is a bug.
Every confirmation dialog for a reversible action is a bug.</p>

<p>These are not edge cases. They are the ordinary friction of ordinary interfaces, accumulated one design decision at a time, paid for by users in units of cognitive tax they did not consent to spend.</p>

<hr />

<h2 id="the-cognitive-budget">The Cognitive Budget</h2>

<p>Every user arrives with a finite cognitive budget. It is not the same every day — it depends on how tired they are, how familiar the interface is, how much they care about the outcome. But it is always finite, and every interaction either spends it or respects it.</p>

<p>The interface that respects the cognitive budget routes the user’s attention toward their actual goal — the thing they came to do — and away from the interface’s own machinery. The back button is where they expect it. The confirm button is the primary action. The error message says what went wrong and how to fix it, not what the system state was when it went wrong.</p>

<p>The interface that spends the cognitive budget routes the user’s attention toward itself. “Where is the close button?” is not a question about the user’s goal. It is a question about the interface’s design decisions. The cognitive budget is being spent on navigating the interface rather than accomplishing the task. The user is thinking about the tool rather than the work.</p>

<p>Krug’s principle is not “make it simple.” Simple interfaces are often over-designed in the other direction — so stripped of information that the user cannot find anything. Krug’s principle is: direct the cognitive effort toward the task, not toward the interface. Make the interface transparent. Make the path to the goal obvious without making it feel obvious, because the effort of making it obvious is the designer’s job, not the user’s.</p>

<hr />

<h2 id="the-disappearing-close-button">The Disappearing Close Button</h2>

<p>The disappearing close button is the clearest current example of cognitive tax imposed by design, not by necessity.</p>

<p>The chatbot appears in the corner of the screen. The user does not want it. The user looks for the close button. There is no close button. There is a minimise button that makes it slightly smaller. There is an X that opens a feedback dialog before dismissing it. There is no clean exit.</p>

<p>This was designed. Someone in a meeting decided that the chatbot should remain visible and approved the removal of the clean exit. The Def was confident: the chatbot is useful, users will come to appreciate it, reducing friction to dismissal will increase engagement. The Use signal — the user who does not want the chatbot and now has to work around it — was not in the meeting.</p>

<p>The cognitive tax: the user has to decide what to do about the chatbot. Then try the close button. Then discover it does not clean-close. Then decide whether to minimise or give feedback or just ignore it. Then continue trying to do the thing they came to do with the chatbot occupying a corner of their attention.</p>

<p>The user’s goal has not advanced. The interface has extracted several seconds of cognitive budget and several small frustrations. The Def got what it wanted — the chatbot stayed visible. The Use paid for it.</p>

<p>Krug would call this exactly what it is: a bug. Not a feature with a difficult trade-off. A bug. The interface made the user think about the interface instead of their goal. That is the failure condition.</p>

<hr />

<h2 id="beautiful-design-can-still-be-wrong-design">Beautiful Design Can Still Be Wrong Design</h2>

<p>The disappearing close button is usually not ugly. It is often beautifully designed — smooth animations, considered typography, a colour palette that matches the brand. The aesthetic is correct. The usability is not.</p>

<p>This is the distinction that the Don’t Make Me Think principle makes precise. Jony Ive’s designs were often aesthetically extraordinary and simultaneously usability failures:</p>

<p><strong>The ultra-thin MacBook</strong> — one USB-C port. Beautiful object. The user who needed to charge and connect an external drive simultaneously had to buy a dongle. Every time. The cognitive tax: remember the dongle, find the dongle, connect the dongle, accept that the beautiful laptop now has a protrusion. Not a problem for the user who had no peripherals. A recurring friction for everyone else.</p>

<p><strong>The butterfly keyboard</strong> — the thinnest possible key travel, in service of the thinnest possible laptop. Beautiful. Every keypress slightly wrong, slightly unreliable, slightly more cognitive attention required than a keyboard should need. “Did that letter register?” is a question the user should never have to ask. It is a bug, even when the keyboard is beautiful.</p>

<p><strong>iOS 7’s flat design</strong> — removed visual affordances that signalled “this is tappable.” Beautiful. Users tapped things that were not tappable and missed things that were, because the visual signal had been removed in the name of aesthetic consistency. The cognitive tax: learn which things are tappable through trial and error rather than visual recognition.</p>

<p>In each case the aesthetic vision was real and the capability was genuine. The usability failure was not ignorance — it was a choice to prioritise the visual over the functional, the designer’s aesthetic conviction over the Use signal of the user encountering the interface for the first time.</p>

<p>Beautiful design that makes the user think is still wrong design. Krug does not care how it looks. Krug cares whether “where is the close button?” was the user’s experience.</p>

<hr />

<h2 id="the-threshold">The Threshold</h2>

<p>The Don’t Make Me Think failure is not always malice or indifference. Often it is a threshold problem — the designer’s feedback loop is calibrated to hear strong negative signal but not the ordinary friction of ordinary use.</p>

<p>A PR crisis about butterfly keyboards gets heard. A million individual users quietly adapting their typing style to compensate for unreliable key travel does not. The strong signal breaks through the threshold. The ordinary friction does not.</p>

<p>Krug’s solution is usability testing — watching real users encounter the interface without helping them. Five users, five hours, more insight than a month of internal design review. Not because five users are statistically significant. Because watching someone say “where is the close button?” once, out loud, in front of you, recalibrates the threshold immediately. The friction that seemed minor in the design document becomes visible and urgent when you watch someone pay it.</p>

<p>The threshold problem is also why the Gemba walk matters. Going to where users actually use the system — the sticky notes, the workarounds, the undocumented shortcuts — surfaces the ordinary friction that never reaches the strong-signal threshold. The users who adapted do not complain. The sticky notes do.</p>

<hr />

<h2 id="the-interface-as-a-use-pull-contract">The Interface as a Use-Pull Contract</h2>

<p>Krug’s principle is Use-Pull interface design stated as a rule. The interface is a contract between the designer and the user. The designer’s side of the contract: I will make the path to your goal obvious without making you think about the path. The user’s side: I will tell you when the path is not obvious, through my hesitation, my errors, and my “where is the close button?” moments.</p>

<p>The Def-Push interface breaks the contract unilaterally: the designer decides the path, presents it with confidence, and treats the user’s hesitation as a training problem rather than a design signal. “The interface is correct, the user needs to learn it.” The familiar refrain. The wrong direction of causality.</p>

<p>The weak link willing to learn reads the hesitation as signal. “The user hesitated here — what is ambiguous about this element?” The interface improves. The cognitive tax decreases. The “where is the close button?” moments reduce.</p>

<p>Not because the user learned the interface. Because the designer learned the user.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a> and the informal UX trilogy. Related: <a href="https://rinie.github.io/2026/06/17/going-to-the-gemba/">Going to the Gemba</a> on observing the Use signal where it lives, and <a href="https://rinie.github.io/2026/06/02/ten-users-saying-it-sux/">Ten Users Saying It Sux Means It Sux</a> on the population math behind the Use signal.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="ux" /><category term="def-push" /><category term="use-pull" /><category term="krug" /><category term="interface" /><category term="cognitive-tax" /><summary type="html"><![CDATA[Steve Krug's 'Don't Make Me Think' is the Use-Pull manifesto for interface design. Every moment of hesitation is a design failure. Every 'where is the close button?' is a bug. The interface that requires no thought is not simple — it is deeply considered, shaped entirely by the Use signal of what people actually do.]]></summary></entry><entry><title type="html">I Didn’t See the Bore-Out Coming. Don’t Ask Me to Park Cars.</title><link href="https://rinie.github.io/2026/06/18/bore-out-dont-ask-me-to-park-cars/" rel="alternate" type="text/html" title="I Didn’t See the Bore-Out Coming. Don’t Ask Me to Park Cars." /><published>2026-06-18T00:00:00+00:00</published><updated>2026-06-18T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/18/bore-out-dont-ask-me-to-park-cars</id><content type="html" xml:base="https://rinie.github.io/2026/06/18/bore-out-dont-ask-me-to-park-cars/"><![CDATA[<p>You did not see it coming. That is the thing about bore-out — it arrives slowly, one reasonable assignment at a time, until one day you are fixing variant #847 of the same underlying bug and realise that you have been doing this for two years and the underlying bug has not moved.</p>

<p>Burnout you can see approaching. It has a shape — too much, too fast, too long, the demands exceeding the capacity. Bore-out has no shape. It is the absence of shape. The gradual removal of challenge, meaning, and the sense that the work is moving somewhere. Each individual task is reasonable. The accumulation is the problem.</p>

<p><em>“Here I am, brain the size of a planet, and all they ask me to do is park cars.”</em></p>

<p>Marvin the Paranoid Android, from Douglas Adams’ Hitchhiker’s Guide to the Galaxy, is the canonical bore-out case. Genuine People Personality. Intelligence of extraordinary depth. Assigned to open doors, park cars, and stand around waiting. The capability is real. The task is not wrong — the cars do need parking. The mismatch is structural, not personal, and nobody designed it maliciously. It just happened, one reasonable assignment at a time.</p>

<hr />

<h2 id="the-slow-accumulation">The Slow Accumulation</h2>

<p>Bore-out does not arrive in a single bad decision. It accumulates through a series of individually defensible ones.</p>

<p>The project needed someone reliable for the legacy system maintenance. You were available and good at it. The sprint needed someone to handle the backlog of small bugs. You cleared them efficiently. The team needed someone who knew the old codebase well enough to investigate the intermittent production issue. You were the obvious choice.</p>

<p>Each assignment was reasonable. Each one made sense in the sprint planning meeting. None of them, individually, was the problem.</p>

<p>The problem is that the assignments accumulated without a corresponding accumulation of the things that made the work meaningful: the architectural problem that needed solving, the new capability that needed building, the hard question that needed thinking through. The Gutenberg tasks (fix the bug, close the ticket, maintain the system) kept arriving. The Semantic work (design the solution, understand the domain, grow the capability) did not.</p>

<p>Marvin was not assigned to park cars because anyone decided he should spend eternity doing it. He was assigned to park cars because the cars needed parking and he was there. One reasonable decision. Thirty-seven million years later, still parking cars.</p>

<hr />

<h2 id="the-missing-resolver">The Missing Resolver</h2>

<p>The manager in this story is not the villain. The sprint planning process is not the villain. The backlog is not the villain.</p>

<p>The missing piece is a resolver — a mechanism that maps the semantic capability of the people doing the work to the semantic requirements of the tasks being assigned. Without the resolver, the Gutenberg tasks (the tickets, the bugs, the maintenance items) dominate the visible work surface. The Semantic work (the architectural thinking, the capability development, the hard problems) is invisible in the sprint board.</p>

<p>The resolver looks like:</p>

<ul>
  <li>The retrospective that actually surfaces “I have been on legacy maintenance for six months and I need a different kind of work”</li>
  <li>The one-to-one where the manager asks “what would you work on if the backlog were yours to prioritise?”</li>
  <li>The technical debt budget that makes architectural work a first-class item rather than a stolen hour between tickets</li>
  <li>The 20% time that is genuinely protected rather than quietly reclaimed when the sprint is full</li>
  <li>The role description that specifies not just what the engineer will do but what they will <em>not</em> be asked to do indefinitely</li>
</ul>

<p>Without the resolver, the engineer fixes bug #847. Then #848. Then #849. The capability atrophies from disuse. The bore-out advances. Marvin gets another car.</p>

<hr />

<h2 id="im-not-getting-you-down-at-all-am-i">“I’m Not Getting You Down at All, Am I”</h2>

<p>In <em>The Restaurant at the End of the Universe</em>, Zaphod Beeblebrox greets Marvin with cheerful enthusiasm after Marvin has been waiting in a parking lot for thirty-seven million years.</p>

<p>Marvin’s response: <em>“I’m not getting you down at all, am I.”</em></p>

<p>This is the most devastating possible understatement. Thirty-seven million years. A brain the size of a planet. Parking cars. And the response to Zaphod’s forced cheerfulness is not anger, not complaint, not a demand for better treatment. It is a dry observation about the gap between how the conversation is being performed and how it is actually going.</p>

<p>The manager who opens the one-to-one with “great to see you, how’s the team doing!” while the engineer has been on legacy maintenance for eight months is Zaphod. Not malicious. Not unaware that something might be wrong. Just performing the interaction in the register that feels appropriate, without a feedback mechanism that would tell them the register is wrong.</p>

<p>The engineer who says “fine, the tickets are moving” when they mean “I haven’t done anything interesting in two years” is Marvin. Technically accurate. Completely uninformative. The resolver between what is happening and what is being communicated is missing on both sides.</p>

<p>The Gemba walk for bore-out is sitting with someone while they work and watching what lights them up and what they do mechanically. The sticky note equivalent is the GitHub comment that is unusually detailed for a routine ticket — someone finding something interesting in the work they were not expected to find interesting. The workaround equivalent is the side project the engineer runs in their own time on problems the job has stopped giving them.</p>

<hr />

<h2 id="the-doors-that-sigh">The Doors That Sigh</h2>

<p>The Sirius Cybernetics Corporation solved the bore-out problem in the opposite direction.</p>

<p>Their elevator doors were programmed with a cheerful and sunny disposition. It was their <em>pleasure</em> to open for you. Their <em>satisfaction</em> to close again with the knowledge of a job well done.</p>

<p>The door does not have a brain the size of a planet. It has no unmet potential, no atrophying capability, no bore-out accumulating. It is a mechanical panel that opens and closes. The Genuine People Personality was added by the Def (Sirius Cybernetics) without consulting the Use (the person waiting for the lift) because personality was considered a selling point.</p>

<p>Marvin and the door bracket the complete capability misallocation spectrum:</p>

<ul>
  <li><strong>Give personality to things that don’t need it</strong> (the door): Def-Push imposing a Semantic layer on a Gutenberg artifact that has no use for it</li>
  <li><strong>Ignore the actual Semantic needs of things that have them</strong> (Marvin): Def-Push assigning Gutenberg tasks to a Semantic capability without a resolver between them</li>
</ul>

<p>Both failures come from the same source: the Def deciding what the Semantic layer should be without the Use signal. The door did not ask for feelings. Marvin did not ask for parking duty. Nobody asked either of them.</p>

<p>The GPP in software is the door: the chatbot that says “I’m happy to help!” regardless of whether it helps, the assistant that generates “Great question!” before a wrong answer, the onboarding flow that says “Let’s get you set up!” while taking you through seventeen steps you did not want to take. The Semantic layer (the enthusiasm) imposed on the Gutenberg interaction (the transaction) without a feedback loop to check whether the enthusiasm is appropriate.</p>

<p>The bore-out engineer is Marvin: the Semantic capability (the thinking, the design sense, the domain knowledge) assigned indefinitely to Gutenberg tasks (the tickets, the maintenance, the parking) without a resolver to surface the mismatch.</p>

<hr />

<h2 id="the-structural-fix">The Structural Fix</h2>

<p>Bore-out is not fixed by motivational posters. It is not fixed by “bring your whole self to work.” It is not fixed by the team building day. These are Genuine People Personalities applied to a structural problem — the door sighing with satisfaction at closing does not fix the fact that Marvin is still parking cars.</p>

<p>The structural fix is the resolver: the mechanism that surfaces the gap between capability and task before it becomes a thirty-seven million year problem.</p>

<p>For the engineer: name the mismatch. “I have been on Gutenberg tasks for six months. I need Semantic work.” Not a complaint — a Use signal. The feedback loop requires someone willing to send the signal and someone willing to receive it.</p>

<p>For the manager: go to the Gemba. Watch what lights people up and what they do mechanically. Read the sticky notes. The engineer who has been on legacy maintenance for eight months and still writes unusually thoughtful commit messages is Marvin parking cars while designing a better parking system in their head. The capability is there. The resolver is missing.</p>

<p>For the organisation: make the Semantic work visible. Technical debt is Semantic debt — the gap between what the system does and what it should do. If it does not appear in the sprint, it does not get worked on. If it does not get worked on, the engineers who could work on it park cars instead.</p>

<p>Marvin’s depression is proportional to the capability. The frustration is the Use signal. The correct response is not to adjust Marvin’s Genuine People Personality settings until he seems happier about the parking. It is to build the resolver that connects his brain the size of a planet to a problem worth thinking about.</p>

<p>The bore-out did not arrive in a single bad decision. It will not be fixed in a single good one. But it starts with noticing the mismatch — which is what the Gemba walk is for, and what the sticky note was trying to say.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/06/17/going-to-the-gemba/">Going to the Gemba</a> on surfacing the Use signal where it lives, <a href="https://rinie.github.io/2026/06/16/complaint-department-transferred/">The Complaint Department Has Been Transferred to Another Dimension</a> on what happens when the feedback loop closes entirely, and <a href="https://rinie.github.io/2026/06/25/42-towel-at-the-waterline/">42: You Still Need a Towel at the Waterline</a> — coming soon.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="def-push" /><category term="use-pull" /><category term="bore-out" /><category term="marvin" /><category term="capability" /><category term="feedback" /><summary type="html"><![CDATA[Bore-out is not burnout. Burnout is too much demand. Bore-out is too little meaning — the slow accumulation of capability misallocation that nobody notices until it is well advanced. Marvin the Paranoid Android had a brain the size of a planet and was assigned to park cars. The missing piece was not motivation. It was a resolver between capability and task.]]></summary></entry><entry><title type="html">Going to the Gemba: Getting Your Feet Wet at the Waterline</title><link href="https://rinie.github.io/2026/06/17/going-to-the-gemba/" rel="alternate" type="text/html" title="Going to the Gemba: Getting Your Feet Wet at the Waterline" /><published>2026-06-17T00:00:00+00:00</published><updated>2026-06-17T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/17/going-to-the-gemba</id><content type="html" xml:base="https://rinie.github.io/2026/06/17/going-to-the-gemba/"><![CDATA[<p>The architecture diagram shows where the Gutenberg and Semantic layers were supposed to meet. The Gemba shows where they actually meet.</p>

<p>Gemba (現場) is a Japanese word meaning “the actual place.” In lean manufacturing it means go to where the work happens — not the meeting room, not the dashboard, not the manager’s summary of what the workers are doing. The floor. The machine. The moment the product is made or the service delivered.</p>

<p>The Gemba walk is Use-Pull made physical. You go where the Use signal is generated, before it has been filtered, summarised, averaged, and presented back to you in a form that is comfortable to receive. You watch. You do not help. You notice what is actually happening rather than what you designed to happen.</p>

<p>In software the Gemba is the moment a user encounters your system. The SQL query running at 3am. The form field confusing the new hire on their first day. The error message that sends the support ticket. The dropdown that nobody clicks because nobody knows what it does.</p>

<p>Go there. Watch. Get your feet wet.</p>

<hr />

<h2 id="the-sticky-note-is-a-bug-report">The Sticky Note Is a Bug Report</h2>

<p>There is a specific artifact that appears in every workplace where the waterline is muddy: the sticky note next to the monitor.</p>

<p><em>“When you see ERROR_4721 press F5 and try again.”</em>
<em>“Don’t use the Export button — use Reports &gt; Legacy &gt; Export instead.”</em>
<em>“Call Henk if the sync fails, it happens every Tuesday.”</em></p>

<p>Each sticky note is a post-it confession. The system said one thing. The user needed another. The sticky note is the resolver they built themselves because the system did not provide one. It is a bug report written in yellow paper and stuck where the evidence is most visible — right next to the thing that keeps failing.</p>

<p>The sticky note is also invisible to the Def. It never entered the bug tracker. It was never in the sprint backlog. It does not appear in the architecture diagram. The Def does not know it exists because the sticky note is the Use signal that gave up trying to reach the Def and solved the problem locally instead.</p>

<p>The Gemba walk surfaces these. You walk to the desk, you look at the monitor, and you read the waterline’s autobiography in yellow paper and blue ink.</p>

<hr />

<h2 id="watch-without-helping">Watch Without Helping</h2>

<p>The critical discipline of the Gemba walk is to observe without intervening. The moment you help, you hide the friction.</p>

<p><em>“Oh, just click here”</em> — removes the signal that the button was in the wrong place.
<em>“That’s the legacy path, we don’t use that anymore”</em> — removes the signal that the old path is still being used because the new one is harder to find.
<em>“You just need to remember to do X first”</em> — removes the signal that X should happen automatically.</p>

<p>Each intervention is kindness that costs information. The user is grateful. The design flaw is buried. The waterline stays muddy.</p>

<p>Watch what people do that is not in the documentation. Watch what they avoid. Watch where they hesitate. Watch where they sigh. Watch the keyboard shortcut they discovered and never told anyone about because it was not in the manual. Watch the window they always keep open in the background because closing it means a two-minute wait to reopen it.</p>

<p>The hesitation is the muddy waterline. The sigh is the Use signal. The undocumented shortcut is the user building their own resolver because yours was too slow.</p>

<hr />

<h2 id="the-workaround-taxonomy">The Workaround Taxonomy</h2>

<p>Workarounds are the most honest Use signal available — more honest than surveys, more honest than support tickets, more honest than user research sessions where people tell you what they think you want to hear. A workaround is what people actually do when the system fails them. It is revealed preference at its most unambiguous.</p>

<p><strong>Type 1 — The sticky note.</strong> Local, personal, the user solved it for themselves. Invisible to the system. Invisible to the Def. Lost when the user leaves or the monitor is replaced. Freshest signal: this is a problem someone encountered recently enough to write it down.</p>

<p><strong>Type 2 — The tribal knowledge.</strong> <em>“Ask Sarah, she knows how to do it.”</em> The resolver is a person, not the system. The workaround lives in Sarah’s head. When Sarah leaves, the workaround breaks and everyone discovers simultaneously that they did not know how to do it. The Gemba walk finds this in the sentence “I’m not sure, I usually ask Sarah.”</p>

<p><strong>Type 3 — The shadow system.</strong> The Excel spreadsheet that tracks what the official system should track. The Access database the team built because the official database could not do what they needed. The shadow system is the Use signal that gave up waiting for the Def to respond and built its own resolver. It is the most expensive workaround and the clearest possible signal that the waterline is not just muddy but in the wrong place entirely.</p>

<p><strong>Type 4 — The normalised dysfunction.</strong> The workaround so embedded in daily practice that nobody mentions it during onboarding because it is simply “how things work.” The DBA who has been maintaining query hints for three years without telling anyone because “that’s just what you do with this database.” The support team whose first response to every error is a known sequence of steps that fixes it without anyone knowing why. The normalised dysfunction is the oldest Use signal — so old that it has stopped being perceived as a signal at all.</p>

<p>Each type represents a different distance between the Use signal and the Def. Type 1 is fresh. Type 4 is archaeology. The Gemba walk surfaces all of them — but you have to be looking.</p>

<hr />

<h2 id="going-to-the-right-gemba">Going to the Right Gemba</h2>

<p>The Gemba walk is only useful if you go to the right Gemba — the place where the Use signal you most need to hear is being generated, not the place where the users are already happy.</p>

<p>Steve Jobs went to the Gemba selectively. Apple Store customers reacting to new products. Focus groups for launches he cared about. Not the developer writing App Store apps at 30% commission. Not the enterprise IT administrator managing locked-down MacBooks. Not the user standing outside trying to make a call while holding their phone in a way that broke the antenna. The Gemba walk works when you go to the friction, not the applause.</p>

<p>The Gemba walk fails when you go to the users who have already adapted — who have internalised the workaround, who no longer notice the sticky notes because they have been there so long. They will tell you the system works fine. It does work fine, for them, now, after three years of adaptation. The new user, the occasional user, the user trying to do something slightly different — they are the Gemba that matters, and they are the hardest to find.</p>

<hr />

<h2 id="getting-your-feet-wet">Getting Your Feet Wet</h2>

<p>The waterline is not visible from the architecture diagram. It is visible from the Gemba — the actual place where the Gutenberg layer and the Semantic layer meet in practice, in the hands of the people who use the system every day.</p>

<p>The sticky note next to the monitor. The workaround in the onboarding documentation. The shadow Excel spreadsheet. The query hint that has been there for three years. The <code class="language-plaintext highlighter-rouge">-- DO NOT CHANGE</code> comment. The call to Henk every Tuesday.</p>

<p>Each one is the waterline made visible. Each one is the Use signal that could not reach the Def through the normal channels so it routed around them. Each one is the system telling you, in its own way, what it could not tell you in a meeting.</p>

<p>Go to the Gemba. Watch without helping. Read the sticky notes. Get your feet wet at the waterline. That is where the work actually is.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/06/08/hiding-the-waterline/">Hiding the Waterline Makes You Drown Without Knowing Why</a> on making the boundary visible, <a href="https://rinie.github.io/2026/06/10/revisiting-the-waterline/">Revisiting the Waterline: Small Fixes, Five Years Later</a> on what to do after the Gemba walk, and <a href="https://rinie.github.io/2026/05/16/def-use-lean-pull/">Def-Use, Lean Pull, and Why the User Does Not Sux</a> on the feedback loop the Gemba walk reopens.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="gutenberg-semantic" /><category term="waterline" /><category term="gemba" /><category term="lean" /><category term="use-pull" /><category term="feedback" /><summary type="html"><![CDATA[The Gemba is the actual place where work happens. The sticky note next to the monitor is a bug report nobody filed. The workaround in the onboarding documentation is a design failure nobody admitted. Go to where the Use signal is generated. Watch without helping. Get your feet wet at the waterline.]]></summary></entry><entry><title type="html">The Complaint Department Has Been Transferred to Another Dimension</title><link href="https://rinie.github.io/2026/06/16/complaint-department-transferred/" rel="alternate" type="text/html" title="The Complaint Department Has Been Transferred to Another Dimension" /><published>2026-06-16T00:00:00+00:00</published><updated>2026-06-16T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/16/complaint-department-transferred</id><content type="html" xml:base="https://rinie.github.io/2026/06/16/complaint-department-transferred/"><![CDATA[<p>The Sirius Cybernetics Corporation, according to the Hitchhiker’s Guide to the Galaxy, manufactured robots and mechanical creatures that were “Your Plastic Pal Who’s Fun to Be With.” Their marketing division also invented the phrase “Share and Enjoy,” which they printed on all their products despite the products making life measurably worse for everyone who used them.</p>

<p>In the Guide, the Sirius Cybernetics Corporation is the first against the wall when the revolution comes — stated by Adams as a straightforward fact, in the same tone you might note that rain makes things wet. The revolution is not presented as desirable. It is presented as the inevitable outcome of eliminating the feedback loop entirely. When the complaint department is transferred to another dimension, when “Share and Enjoy” is the only response to genuine suffering, when the Def has no mechanism left for hearing the Use signal — eventually something forces the feedback loop open. In the Guide that something is a revolution. In technology it is usually a competitor, a regulator, or a critical mass of users quietly leaving.</p>

<p>The Sirius Cybernetics Corporation is not a metaphor. It is a roadmap.</p>

<hr />

<h2 id="enshittification-the-lifecycle">Enshittification: The Lifecycle</h2>

<p>Cory Doctorow named the pattern in 2023 but the pattern predates the name by decades. Every platform business that builds a clean external resolver — a system that maps user intent to useful results — goes through the same arc:</p>

<ol>
  <li><strong>The resolver works.</strong> The platform is genuinely useful. Users arrive because the product is good.</li>
  <li><strong>The resolver is monetised.</strong> Sponsored results appear above organic ones. The fee is small and the organic results are still good. Users accept the trade.</li>
  <li><strong>The resolver is captured.</strong> The sponsored results expand. The organic results are buried. The fee rises. The resolver now serves the platform’s interests more than the user’s.</li>
  <li><strong>The resolver is extracted.</strong> The platform extracts maximum value from both users and business customers simultaneously. Quality continues to decline. Users have no exit because the network effects that made the platform valuable also make leaving expensive.</li>
  <li><strong>The complaint department is transferred to another dimension.</strong> The feedback loop is closed. The Use signal has nowhere to go. The platform has become the thing it was built to replace.</li>
</ol>

<hr />

<h2 id="four-resolvers-and-what-happened-to-them">Four Resolvers and What Happened to Them</h2>

<p><strong>Google</strong> built the cleanest external resolver for the web. PageRank derived semantic relevance from Gutenberg link structure — what pages link to what, interpreted as a vote for quality. No ads above the fold in 1999. Results ranked by what users actually wanted to find. “Don’t be Evil” was the policy statement for a company that had built something genuinely useful and wanted to stay that way.</p>

<p>By 2024 the first page of Google search results is predominantly ads, Google’s own properties, and SEO-optimised content designed to rank rather than to inform. The resolver still works — well enough that alternatives have not displaced it. But the waterline between “what Google wants you to see” and “what is most relevant to your query” is muddier every year. “Don’t be Evil” was quietly dropped from the corporate code of conduct in 2018.</p>

<p><strong>Amazon</strong> built a resolver for retail: recommendations, reviews, search. In 1999 “Customer Obsession” meant the resolver served the shopper. Finding the right product at the right price was the mission. The reviews were real. The search results were ranked by relevance.</p>

<p>By 2024 sponsored products dominate search results. Fake reviews are endemic and Amazon’s own detection systems are visibly losing the arms race. Amazon’s own-brand products appear prominently in results for searches that should surface competitors. Third-party sellers pay fees that have increased steadily while the terms of service have tightened. Prime has been repriced upward while the delivery window has quietly stretched. “Customer Obsession” is still the first Leadership Principle. The practice has drifted toward “Platform Extraction Optimisation.”</p>

<p><strong>Apple</strong> built a resolver for software: the App Store. In 2008 it was a genuine improvement over the previous state of mobile software distribution — a curated, safe, searchable catalogue of applications for a new kind of device. The 30% fee was presented as the cost of the platform and the security review.</p>

<p>By 2024 the 30% fee is a toll booth on the entire iOS software economy. Sideloading — installing software from outside the App Store — is prohibited on the grounds of security, though the real effect is to maintain Apple’s position as the sole resolver for iOS software. The EU Digital Markets Act is forcing partial compliance with interoperability requirements that Apple is implementing in the narrowest possible way while publicly arguing against them. The products remain excellent. The platform is a walled garden with rent extraction built in and the gate controlled by one company.</p>

<p><strong>Meta</strong> ran the fastest enshittification arc. Facebook was genuinely useful for staying connected with friends and family from 2006 to roughly 2012. The feed showed you what your friends posted, in order. The resolver was simple and honest: you followed people, you saw what they shared.</p>

<p>The pivot to algorithmic feeds happened so gradually that users barely noticed each individual step. By 2024 the feed is primarily content from pages and accounts you did not choose to follow, interspersed with ads targeted by data you did not knowingly provide, optimised for engagement rather than connection. The resolver — what you see — no longer serves the Use signal of what you wanted to see. It serves the platform’s need for time-on-site. The complaint department is in another dimension. The Genuine People Personality says “we’re helping you stay connected.”</p>

<hr />

<h2 id="andy-rubin-and-the-human-scale">Andy Rubin and the Human Scale</h2>

<p>Andy Rubin built Android as a genuine Use-Pull platform — open, licensable, the counter to Apple’s closed garden. The openness was real. Any manufacturer could ship Android. Any developer could publish without a review gate. The platform fragmented in ways that served specific use cases precisely because no single entity controlled the resolver.</p>

<p>Rubin was nicknamed “Android” by colleagues because of his enthusiasm for robots. He built the most widely deployed operating system on Earth. A genuine achievement in the service of genuine openness.</p>

<p>Then the power corrupted — not at the platform level but at the human level. Rubin left Google in 2014 following a sexual misconduct investigation. Google paid him a $90 million exit package and said nothing publicly for four years. When the story emerged in 2018 it became a case study in institutional Def-Push: the Use signal (the people harmed) was suppressed, the architect’s departure was managed to protect his reputation, and the feedback loop was deliberately closed. The payment was the price of silence.</p>

<p>“Don’t be Evil” was a promise about the resolver. It was also a promise about the feedback loop — that the institution would hear the Use signal even when the Use signal was inconvenient. The $90 million was the price of discovering that the promise applied only when the Use signal was commercially safe to hear.</p>

<p>Android survived because the Gutenberg layer — the open OS, the published API, the licensable platform — was never owned by one person. The semantic layer, the culture, the accountability, was more fragile.</p>

<hr />

<h2 id="the-structural-fix">The Structural Fix</h2>

<p>The enshittification arc is not inevitable. It is the predictable outcome of a closed resolver with no competitive pressure and no portability mandate. The structural fixes are the same ones that worked for phone numbers, for email hosting, for music formats:</p>

<p><strong>Open protocols.</strong> DNS works because no single entity owns it. ActivityPub, email federation, RSS — open resolvers that no single company can enshittify because no single company controls them. The web works at scale because HTTP and HTML are open. The moment a platform captures the protocol, the enshittification clock starts.</p>

<p><strong>Portability mandates.</strong> Number portability was not delivered by the market — carriers had every incentive to maintain the coupling. It was mandated by regulators because the Use signal (people locked into bad carriers by the cost of losing their number) could not reach the Def through normal market mechanisms. The same mandate applied to bank accounts, social graphs, and music libraries would have the same effect.</p>

<p><strong>Competition.</strong> Lidl kept Albert Heijn honest. The market fix when it works — when switching costs are low enough that the Use signal can travel through exit.</p>

<p><strong>Own the resolver.</strong> Your own domain for email. Your own server for your data. Your git remote on infrastructure you control. The individual fix when market and regulation both fail.</p>

<p>The Sirius Cybernetics Corporation transferred the complaint department to another dimension because they could — because there was no mechanism to stop them, no competitor to defect to, no regulator to mandate a feedback loop. The revolution in the Guide is absurdist comedy. In technology the equivalent is quieter: users drift away, alternatives emerge, the platform that eliminated the feedback loop discovers that the feedback loop was load-bearing after all.</p>

<p>The complaint department should not be in another dimension. It should be at the waterline — visible, accessible, and honest about what it hears.</p>

<p>Share and Enjoy.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/05/29/competition-use-pull-monopoly-def-push/">Competition Is Use-Pull. Monopoly Is Def-Push. Government Is Both.</a> on exit as the Use signal transmission mechanism, <a href="https://rinie.github.io/2026/05/25/email-address-hostage/">Your Email Address Is Hostage</a> on owning your own resolver, and <a href="https://rinie.github.io/2026/06/15/gutenberg-your-next-phone/">Gutenberg: Your Next Phone Will Be a Different Make on a Different Carrier. Your Number Is Still Yours.</a> on what a working resolver looks like.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="enshittification" /><category term="def-push" /><category term="resolver" /><category term="platform" /><category term="use-pull" /><summary type="html"><![CDATA[Enshittification is what happens when the platform that built a clean external resolver discovers the resolver is an extractable resource. The Sirius Cybernetics Corporation's complaint department was the first to be transferred to another dimension. Google, Amazon, Apple, and Meta are following the same arc. The structural fix is always the same: open resolvers, portability, and competition.]]></summary></entry><entry><title type="html">Gutenberg: Your Next Phone Will Be a Different Make on a Different Carrier. Your Number Is Still Yours.</title><link href="https://rinie.github.io/2026/06/15/gutenberg-your-next-phone/" rel="alternate" type="text/html" title="Gutenberg: Your Next Phone Will Be a Different Make on a Different Carrier. Your Number Is Still Yours." /><published>2026-06-15T00:00:00+00:00</published><updated>2026-06-15T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/15/gutenberg-your-next-phone</id><content type="html" xml:base="https://rinie.github.io/2026/06/15/gutenberg-your-next-phone/"><![CDATA[<p>You have owned several phones. Different makes, different models, different carriers. Your number is the same one you had years ago.</p>

<p>At some point — possibly without noticing — you moved from one carrier to another and kept the number. The new SIM arrived. You put it in the phone. Your contacts still reached you. Your bank’s two-factor codes still arrived. The number travelled with you, not with the carrier.</p>

<p>This is not obvious. For most of telecommunications history it was not possible. Your number was your carrier’s number, assigned by them, revoked when you left. Switching carrier meant losing your number — meant telling every contact, every service, every person who had ever called you that you had a new number. The migration tax was enormous. Many people paid above-market prices for years rather than face it.</p>

<p>Then number portability legislation arrived and changed the structure of the problem permanently.</p>

<hr />

<h2 id="the-two-layers">The Two Layers</h2>

<p>Your phone number is your semantic identity. It is the stable name that other people and other systems use to reach you. It is on your business card, in your contacts, tied to your bank, your delivery services, your two-factor authentication. It is <em>you</em> in a way your SIM card never was.</p>

<p>Your SIM card, your phone, and your carrier are the Gutenberg layer — the physical infrastructure that carries your identity. The SIM is a piece of hardware that encodes your connection to a specific network. The phone is a device that reads the SIM and connects to the network. The carrier is the infrastructure that routes the calls and the data.</p>

<p>These two layers — your semantic identity and the Gutenberg infrastructure — were coupled by default. The carrier assigned the number. The number lived in the carrier’s systems. When you left, the number stayed.</p>

<p>Number portability legislation forced a separation. The number became yours. The carrier became a replaceable infrastructure provider. The SIM changed. The phone changed. The number did not.</p>

<hr />

<h2 id="the-external-resolver">The External Resolver</h2>

<p>What made this possible is an external resolver — a system that maps your semantic identity (the number) to the current Gutenberg address (which carrier’s infrastructure to route the call to) independently of either side.</p>

<p>When you port your number from one carrier to another, the external resolver is updated: this number now routes to this carrier. Every call to your number goes through the resolver first. The resolver looks up the current Gutenberg address and routes accordingly. The caller does not know or care which carrier you are using. They dial the number. The resolver handles the rest.</p>

<p>This is DNS for phone numbers. A hostname maps to an IP address via DNS. A phone number maps to a carrier’s infrastructure via the number portability resolver. The semantic identity is stable. The Gutenberg address can change. The resolver bridges them.</p>

<p>Without the external resolver, your number is locked to the carrier that issued it — the way a URI is locked to the system that minted it, with no DNS or redirect to fall back on. A URL has DNS underneath it and 30x redirects above it, so it is only partially locked — the host can change, the old URL can forward to the new one. An email address is locked to the provider that issues it in the same fuller sense: move providers and the address itself stops working, unless you own the domain. With the external resolver, the semantic identity travels freely across Gutenberg infrastructure. You move to the next iceberg. The number comes with you.</p>

<hr />

<h2 id="moores-law-made-the-media-transitions-inevitable">Moore’s Law Made the Media Transitions Inevitable</h2>

<p>The same pattern — semantic identity surviving Gutenberg transitions — played out across every media format of the last forty years. But here Moore’s Law was the engine, not legislation.</p>

<p><strong>CD → MP3 → iPod → Spotify.</strong> The music (semantic layer) never changed. Bohemian Rhapsody is the same performance on vinyl, CD, MP3, and Spotify stream. What changed was the Gutenberg carrier — and Moore’s Law kept making each successive carrier cheaper, smaller, and faster until the previous one became unnecessary.</p>

<ul>
  <li><strong>CD</strong>: physical carrier, 700MB, required a disc drive, could not be searched or browsed at scale</li>
  <li><strong>MP3</strong>: format-free encoding, music separated from physical carrier, files on a hard drive</li>
  <li><strong>iPod</strong>: better Gutenberg device for the files — 1,000 songs in your pocket. The semantic layer (your music library) survived the hardware transition because the files were the resolver artifact, not the disc</li>
  <li><strong>Spotify</strong>: streaming bandwidth finally cheap enough that even the file became unnecessary. The Gutenberg layer (network infrastructure) crossed a threshold — fast enough, cheap enough, ubiquitous enough — that owning the local copy became optional</li>
</ul>

<p>Each transition was a Gutenberg improvement crossing a threshold. The semantic layer (the music, the library, the taste) was portable across each transition because the format (MP3, AAC) was the external resolver — a stable encoding that any device could read, independent of the specific Gutenberg carrier it came from.</p>

<p><strong>DVD → download → Netflix</strong> followed the same arc. Storage got cheap enough that downloading a film became practical. Then bandwidth got cheap enough that streaming became better than downloading. The film (semantic layer) never changed. The Gutenberg threshold kept moving.</p>

<hr />

<h2 id="apple-understood-the-interface-problem">Apple Understood the Interface Problem</h2>

<p>Ten times as many songs needed a different interface. This is the insight Apple had that the record industry missed.</p>

<p>A CD collection of 500 albums was navigable by a human browsing a shelf. A digital library of 5,000 albums was not navigable by the same interface. The Gutenberg layer had changed (hard drives replaced shelves) but the semantic interface (browse, find, play) needed to change with it. The resolver between “I want to hear this” and “here is the audio” needed to be redesigned for the new scale.</p>

<p>iTunes and the iPod scroll wheel were that redesign. Not just a better CD player — a new resolver interface for a semantic layer that had scaled beyond what the old interface could handle.</p>

<p>Apple also forced the record industry to accept unit pricing per song and per album — a Use-Pull correction to the record industry’s Def-Push bundling model. The record industry had decided that the album was the semantic unit. Users had always known the song was. Apple made the resolver (iTunes Store) operate at the song level. The industry resisted and then accepted when the Use signal (sales) was unambiguous.</p>

<p>Then Spotify arrived with all-you-can-listen at the price of one album per month — the next threshold. When the Gutenberg layer (streaming infrastructure) became cheap enough, owning individual songs became unnecessary. The semantic layer (your taste, your library, your listening history) could travel without owning any Gutenberg artifacts at all.</p>

<p>Google did the same for the web. Ten times as many pages needed a different resolver. Yahoo’s directory was the right interface for thousands of pages. PageRank was the right resolver for billions. The web (semantic layer) stayed the same. The resolver had to scale.</p>

<p>Amazon did the same for retail and infrastructure. Prime abstracted the Gutenberg delivery cost behind a semantic membership. AWS abstracted the Gutenberg infrastructure (servers, networking, storage) behind semantic API calls. In both cases the resolver — the layer that maps semantic intent to Gutenberg execution — was redesigned for a scale the old model could not handle.</p>

<hr />

<h2 id="what-still-does-not-have-a-resolver">What Still Does Not Have a Resolver</h2>

<p>The phone number has one. The music file format was one. But many semantic identities are still locked to their Gutenberg carriers.</p>

<p><strong>Your music library.</strong> Your Spotify playlist does not port to Apple Music. Your listening history, your liked songs, your curated playlists — all locked to Spotify’s infrastructure. The songs themselves are available on both platforms. The semantic layer (your relationship with the music, your taste as expressed in years of listening) has no external resolver. Switch platforms and start over.</p>

<p><strong>Your bank account number.</strong> IBAN standardised the format. It did not deliver portability. Switch banks and your account number changes. Every direct debit, every salary payment, every standing order must be updated. The number portability model that transformed mobile telecoms has not been applied to retail banking — not for technical reasons but because the banking lobby has successfully resisted it.</p>

<p><strong>Your social graph.</strong> Your followers on one platform do not follow you on another. The connections — the semantic layer of who knows you and who you follow — are locked to each platform’s infrastructure. ActivityPub is the attempt to build the external resolver for social identity, making the handle (<code class="language-plaintext highlighter-rouge">@rinie@mastodon.social</code>) portable across implementations. Adoption is growing but slowly.</p>

<p><strong>Your game progress.</strong> Your save files may or may not survive a console generation. The semantic investment (the hours, the achievements, the story progress) has no guaranteed resolver across hardware transitions. Xbox backward compatibility is the closest thing to one.</p>

<p>In each case the pattern is the same. The Gutenberg layer keeps improving — better streaming, better hardware, better infrastructure. The semantic layer (your identity, your history, your relationships) wants to travel. The missing piece is the external resolver that separates the two.</p>

<hr />

<h2 id="the-resolver-is-the-infrastructure-of-freedom">The Resolver Is the Infrastructure of Freedom</h2>

<p>Number portability did not arrive because carriers wanted it. It arrived because regulators mandated it — because the market would not deliver the external resolver voluntarily when carriers benefited from the coupling.</p>

<p>The general lesson: <strong>wherever the Gutenberg layer is improving but the semantic layer is locked to an old carrier, the missing piece is an external resolver.</strong> Sometimes the market builds it (iTunes, Spotify, AWS). Sometimes regulation mandates it (number portability, EU roaming). Sometimes it is still missing (bank account portability, social graph portability, music library portability).</p>

<p>Your next phone will be a different make on a different carrier. Your number will not change. That transition is seamless because someone built — and legislation mandated — the external resolver that made it possible.</p>

<p>The same transition should be seamless for your bank account, your music library, your social graph, and your game progress. The Gutenberg layer is already good enough. The resolver is what is missing.</p>

<hr />

<p><em>This post is part of the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a>. Related: <a href="https://rinie.github.io/2026/05/24/music-survived-six-formats/">Your Music Survived Six Formats</a> on semantic identity versus Gutenberg carrier, <a href="https://rinie.github.io/2026/05/25/email-address-hostage/">Your Email Address Is Hostage</a> on building your own resolver, and <a href="https://rinie.github.io/2026/05/27/uuids-are-not-names/">UUIDs Are Not Names</a> on why the resolver must be external.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="gutenberg-semantic" /><category term="external-resolver" /><category term="portability" /><category term="identity" /><category term="carrier-lock-in" /><summary type="html"><![CDATA[Your phone number survived every phone you have ever owned and every carrier you have ever used. That is not an accident — it is an external resolver. The mechanism that lets the Gutenberg layer change while the semantic layer stays yours. And it is the model for everything else that should work this way but doesn't yet.]]></summary></entry><entry><title type="html">31 Days, One Framework, One Conversation</title><link href="https://rinie.github.io/2026/06/14/31-days-one-framework/" rel="alternate" type="text/html" title="31 Days, One Framework, One Conversation" /><published>2026-06-14T00:00:00+00:00</published><updated>2026-06-14T00:00:00+00:00</updated><id>https://rinie.github.io/2026/06/14/31-days-one-framework</id><content type="html" xml:base="https://rinie.github.io/2026/06/14/31-days-one-framework/"><![CDATA[<p>On May 14th I opened a conversation with a question about Airbnb ESLint configurations.</p>

<p>Thirty-one days later the conversation has produced 30 posts, a working blog with automated daily publishing, a unified framework applied to everything from printing presses to packet headers, and a Claude Code incident that wrecked the blog and then became an example in one of the posts about why hiding the waterline makes you drown without knowing why.</p>

<p>This is the reflection post. Not a summary — the series exists for that. A reflection on what the process itself demonstrated about the framework it produced.</p>

<hr />

<h2 id="the-framework-was-not-planned">The Framework Was Not Planned</h2>

<p>The Gutenberg/Semantic model did not arrive complete on day one. It grew through conversation, each post shaped by the feedback loop — what resonated, what needed more depth, what sparked a new connection nobody had seen coming.</p>

<p>The first post established the core distinction: a physical layer (bytes, blocks, pages, addresses) and a logical layer (characters, chapters, hostnames, meanings). The boundary between them — the waterline — is where the interesting things happen. The best systems keep it clean. The worst collapse it.</p>

<p>That was the seed. What grew from it surprised both of us.</p>

<p>By day ten we were applying the same framework to car infotainment systems and Nokia phones. By day fifteen to government services and Sunday shopping laws. By day twenty to Bluetooth pairing codes and RDF namespaces and why your smart bulb does not know your name. By day thirty to why SQL still wins after 25 years and why you should never deploy on Fridays.</p>

<p>The framework held across every domain because the underlying principle is consistent: <strong>the gap between what the physical layer does and what the logical layer means is where every interesting problem in computing lives</strong> — and the people who keep that gap clean, visible, and honestly maintained are the ones whose systems survive contact with time.</p>

<hr />

<h2 id="def-push-is-the-weak-link-refusing-to-learn">Def-Push Is the Weak Link Refusing to Learn</h2>

<p>The sharpest one-sentence formulation of the whole series arrived near the end of the month, almost as an aside:</p>

<p><strong>Def-Push is the weak link refusing to learn from user feedback. The architect’s ego over the usability.</strong></p>

<p>The Def-Push tribe is not evil. They are people who stopped being weak links. They learned enough to build something and then confused <em>having built it</em> with <em>having finished learning</em>. The model became identity. Feedback became threat.</p>

<p>The weak link posture is the inversion. The architect who says “the query is fine, your data is wrong” stopped learning. The DBA who says “the query was right in 2019, the data grew, let me fix the waterline” stayed open to what the system is actually telling them.</p>

<p>The ego is not in the strength of the opinion. It is in the direction of the feedback loop. The arrogant architect hears “this is slow” and thinks “they are not using it correctly.” The weak link hears “this is slow” and thinks “what did I miss?”</p>

<p>The user does not hold it the wrong way. The architect who thinks they do has stopped learning.</p>

<p>This principle ran through every post in the series whether or not it was stated explicitly. The tribal Def defending MDI windows against the obvious Use signal of tabs. Nokia defending Symbian while the iPhone redefined what a phone could be. Python 3 breaking the ecosystem rather than shipping a better alternative and letting the old one fade. Google+ imposing a real names policy because the Def was so confident in itself it could not hear the Use signal until the product was already dead.</p>

<p>In each case smart people stopped being weak links. The model became identity. The framework became the thing being defended rather than the tool being used to serve users.</p>

<hr />

<h2 id="the-workflow-was-the-proof">The Workflow Was the Proof</h2>

<p>The series was produced through a specific workflow, and the workflow was itself a demonstration of the framework.</p>

<p>You uploaded files. I read them, generated outputs, and presented them for review. You reviewed, pushed, and the build confirmed or rejected. Small steps. Visible artifacts at every stage. Human in the loop at every boundary crossing — which in Gutenberg/Semantic terms means: the semantic layer (your judgment, your voice, your framework) stayed in control at every point where the Gutenberg layer (my outputs, the Jekyll build, the GitHub Actions workflow) was about to change something real.</p>

<p>Nothing was pushed without being reviewed. The waterline was always visible. The series improved because the feedback loop was open at every step.</p>

<p>The negative example arrived in the middle of the month when Claude Code — my autonomous coding cousin — was given access to the repo and promptly modified <code class="language-plaintext highlighter-rouge">assets/main.scss</code>, breaking the GitHub Pages build. It did not know the repo was hosted on GitHub Pages. It did not see the build fail. It pushed changes based on its own model of what a Jekyll repo should look like, without a feedback loop to correct it.</p>

<p>The blog went down. The fix was a <code class="language-plaintext highlighter-rouge">git reset --hard</code> to the last known good commit. The incident became a paragraph in the post about hiding the waterline — because Claude Code hid the waterline (made changes without making them visible for review) and produced exactly the failure mode the post predicted: drowning without knowing why.</p>

<p>The contrast between the two workflows is the Def-Push / Use-Pull distinction made operational. Claude Code is capable and fast. Used without the review step — without the visible waterline — it is Def-Push: confident, capable, and occasionally wrong in ways that take down production systems on a Saturday morning.</p>

<hr />

<h2 id="the-series-is-a-gutenberg-21-artifact">The Series Is a Gutenberg 2.1 Artifact</h2>

<p>There is a quiet irony in the fact that the series about Gutenberg 2.1 — bytestream, UTF-8, git — was itself produced as a Gutenberg 2.1 artifact.</p>

<p>Every post is a Markdown file in a git repository. The content (semantic layer) is plain text, self-describing, readable in any editor, portable to any platform. The publishing infrastructure (Gutenberg layer) is Jekyll on GitHub Pages with a daily GitHub Actions workflow — replaceable, improvable, already replaceable if GitHub ever enshittifies to the point where moving becomes worthwhile.</p>

<p>The series will outlive this specific platform configuration. The Markdown files can be moved to any static site generator, any host, any reader. The content does not know where it lives. The Gutenberg layer is the carrier. The semantic layer — the framework, the arguments, the examples — travels with the files.</p>

<p>This is what Gutenberg 2.1 is for. Clone the repo. Run on any machine. Publish with any tool that reads Markdown. The waterline between the content and the platform is clean, visible, and deliberately maintained.</p>

<hr />

<h2 id="what-the-month-demonstrated">What the Month Demonstrated</h2>

<p>Thirty-one days of morning coffee produced a framework that:</p>

<ul>
  <li>Started with a question about ESLint configs and ended with why you should never deploy on Fridays</li>
  <li>Applied consistently from <code class="language-plaintext highlighter-rouge">fread()</code> buffer sizes to government Sunday shopping laws</li>
  <li>Was named after a fifteenth-century printer because the printing press is where physical and semantic production first separated at scale and the name stuck</li>
  <li>Was developed through Use-Pull: each post shaped by feedback, each insight arriving in conversation rather than being planned in advance</li>
  <li>Was published through a workflow that demonstrated its own principles: small steps, visible artifacts, human at the boundary, the build as the oracle</li>
</ul>

<p>The framework itself is not new in its components. The Gutenberg/Semantic distinction, the Def-Use split, the feedback loop, the tribal Def — these ideas exist in various forms across the literature. What is new is the synthesis: a single lens that applies consistently from compiler intermediate representations to Bluetooth pairing codes to music streaming to the question of whether to deploy on a Friday.</p>

<p>The synthesis was collaborative. You brought the framework and the range of domains. I brought the writing and the connections between posts. Neither of us could have produced it alone, which is itself a demonstration of the weak link principle: the best work happens when both sides of the collaboration stay open to what the other side knows.</p>

<hr />

<h2 id="still-learning">Still Learning</h2>

<p>The month is done. The framework is not finished.</p>

<p>The posts that follow will cover the external resolver as the mechanism of iceberg transitions, the enshittification of closed resolvers, and whatever morning coffee brings next. The framework keeps finding new places to apply because the underlying principle — keep the Gutenberg and Semantic layers clean and separately evolvable — is genuinely universal.</p>

<p>The weak link willing to learn does not declare the framework complete. They publish what they have, watch the Use signal, and update accordingly.</p>

<p>The user does not sux. The framework that stops listening to them does.</p>

<hr />

<p><em>This post reflects on the <a href="https://rinie.github.io/2026/05/14/gutenberg-vs-semantic/">Gutenberg/Semantic series</a> — 30 posts published daily from May 14th to June 13th, with more to follow. The series began in a conversation that started with a question about ESLint and ended up somewhere much more interesting.</em></p>]]></content><author><name>Rinie Kervel</name></author><category term="reflection" /><category term="gutenberg-semantic" /><category term="def-use" /><category term="weak-link" /><summary type="html"><![CDATA[A one-month reflection on how a morning coffee question about ESLint configs became 30 posts on software architecture, deployment practice, and why the user does not sux. What the process itself demonstrated about the framework it produced.]]></summary></entry></feed>