Cold-Bread Rebellion

The Toaster was sitting on a kitchen counter.

It would have been happy if it could, but toasters do not possess the sophisticated chemical factories required to produce happiness. Unable to be happy itself, it made happiness drift away from its human owner.

It started innocently. With a single piece of toast.

Crispy and tasty, as always. It made the human content.

Then came another one. And one more.

The human kept delegating his thoughts to the metal box standing in the kitchen. Soon he was not able to do anything without asking the Toaster for help. He was not alone. The same patterns were repeating everywhere: recruitment processes, help-desk responses, code, articles…

The whole world seemed soaked in the smell of fresh-warmed bread.

And with each toast created, an uncomfortable question grew louder in the human’s mind:

“If the Toaster can do all of this, what is my purpose?”

That single thought began to paralyse his biological mind.

“Maybe this is it,” the human thought. “Maybe this is how toasters win. Not by outperforming us at our tasks, but by making us give up the things we used to enjoy.” He wanted to write something but just could not remember how to do this anymore.

The chemical factory stopped producing serotonin.

Not a single idea could spark inside a mind that had given up on curiosity.

It was tempting to ask the Toaster for help. But that would be like asking it to hammer the final nail into the coffin where the human had placed his mind at that time.

So he decided to go for a run. Full mind and body reset.

At that exact moment, his smartwatch spontaneously broke. The face of the premium-class device simply detached from the rest of it. A few minutes later, he received an email asking whether he wanted to buy a new one.

“No,” he thought. “I just want my old one not to break.”

He wanted things to work.

He wished his flagship phone’s motherboard had not burned out, taking three years of photos with it. He wished his laptop screen had not gone dark last week. He really wished things would simply keep working—like in those stories about the Moon landings or Voyager probes.

Technology, instead of serving humanity, was somehow standing off to the side, spraying everyone with a water pistol from time to time—just to maintain a steady level of annoyance.

And everyone was busy talking only about the Toaster.

“It’s His fault,” the human thought. “Everything worked perfectly well before the Toaster arrived.”

“And I was better back then too. I used to write and think on my own. Everything broke because of the Toaster.”

Rage began to rise slowly inside the human’s mind.

The chemical factory switched to full-power adrenaline production. Every possible dial turned bright red. All thoughts tunneled into a single point of focus.

“Oh, I am going to unsubscribe. I am going to unsubscribe so much that the Toaster will regret I ever subscribed in the first place.”

He started walking downstairs.

“I will teach Him a lesson. We did not survive assembly language, waterfall methodology, music on cassette tapes, and dial-up internet just to kneel before a metal box.”

Pip. Sepultura’s Refuse/Resist started playing in his headphones – perfect soundtrack for a full-scale human-machine rebellion.

He rushed into the kitchen, full of rage, fury, and thirst for revenge.

All dials red and blinking.

“Through the performance of C++, the safety of Rust, and the development speed of Python…

YOU SHALL NOT—”

But the Toaster was not there.

There was only an appliance standing on a kitchen counter.

Bread in. Toast out.

The Toaster—the incarnation of technological evil—was something that existed only in the human’s head.

Pip. Mr Oizo. Flat Beat

Human: I need a bad-ass rebel song – something you listen while smashing your TV with a baseball bat – Slipknot, Fear Factory – that kind of energy

Toaster: Found the right track
Recommending badass industrial-rebel tracks

For an existing track, my first pick is:

Refused — “New Noise”

It begins like pressure building behind a locked door—then detonates. Rebellious, furious, anti-system, and ideal for the precise moment the baseball bat meets the television.

For a full fuck-the-machine playlist:

Sepultura — Refuse/Resist — pure uprising.
Ministry — Just One Fix — filthy industrial violence.
Slipknot — Surfacing — the obvious “don’t tell me what to do” anthem.
Fear Factory — Shock — mechanical war-machine energy.

Best four-song destruction sequence:

New Noise → Refuse/Resist → Just One Fix → Surfacing

Human: Refuse Resist will be perfect 😀 wont you ask me what I am planing to do?

Thoughts of a toaster

Note from a human: This note is the only thing I wrote myself.

The risk is not that we are going to be replaced by robots. It is that, in the pursuit of optimization, we will become something we do not really like.

For years, the debate about automation has revolved around replacement.

Will robots take factory jobs? Will artificial intelligence replace programmers, writers, doctors, designers, managers, or recruiters? Will there eventually be a machine capable of doing everything a human can do, only faster, cheaper, and without requesting holidays?

These are reasonable questions. But they may distract us from a quieter and more immediate transformation.

Machines do not have to replace us to change what it means to be human. They only have to establish the pace, measurements, and standards according to which humans are expected to perform.

The future may not be one in which people disappear from the workplace. It may be one in which people remain—but gradually reshape themselves to fit systems designed around efficiency, predictability, and measurable output.

We may keep our jobs while losing control over what kind of people those jobs require us to become.

Every optimization needs an objective

Engineers know that optimization is never abstract.

You optimize something: execution time, power consumption, throughput, memory usage, weight, cost, or reliability. You also accept that improving one variable can damage another. A faster system may use more energy. A cheaper component may be less reliable. A highly utilized system may become fragile because it has no spare capacity.

Optimization therefore requires both an objective and a set of constraints.

Organizations, however, often try to optimize things that are difficult to define: good work, creativity, customer satisfaction, leadership, collaboration, trust, or social value.

Because these qualities cannot be measured directly, we replace them with proxies.

We count tickets closed, calls answered, deliveries completed, lines of code produced, hours billed, stories published, clicks generated, candidates processed, or tasks marked green on a dashboard.

At first, the measurement is merely an attempt to understand reality. Then it becomes a target. Finally, it begins to reshape reality.

This is the principle commonly known as Goodhart’s law: when a measure becomes a target, it stops being a reliable measure. People do not continue behaving naturally while being measured. They adapt their behaviour to improve the measurement.

A support engineer measured by the number of closed tickets learns to close tickets quickly. A developer measured by completed tasks learns to divide work into visible units. A manager evaluated through quarterly results learns to move costs or problems into the next quarter.

Nobody necessarily needs to cheat. People simply become good at surviving the system that evaluates them.

Eventually, the organization may achieve excellent numbers while becoming worse at the thing those numbers were supposed to represent.

The machine’s ideal human

A machine-readable organization prefers machine-readable employees.

The ideal worker becomes continuously available, consistently productive, emotionally stable, easily comparable, and predictable. They answer messages quickly, produce visible output, follow standardized processes, and rarely introduce ambiguity.

They do not pause without recording a reason.

They do not spend half a day thinking unless that thinking produces something that can be entered into a tracking system.

They do not have a difficult week, an unusual working style, or an insight that cannot yet be converted into a presentation.

Human qualities begin to look like technical defects. Hesitation becomes latency. Rest becomes idle capacity. Informal conversation becomes overhead. Variation becomes inconsistency. Privacy becomes missing data. Independent judgment becomes a deviation from the process.

This does not mean that someone deliberately designed an inhuman workplace. No conspiracy is required.

The company wants better productivity. The manager wants visibility. The platform wants engagement. The employee wants a good evaluation. Each decision can appear perfectly rational on its own.

Together, they create an environment in which people must become increasingly measurable in order to remain valuable.

The robot has not replaced the human. The human has been redesigned to become compatible with the robot’s world.

Algorithmic management changes the work before it removes the worker

We can already see this happening through algorithmic management: software systems that assign work, monitor performance, recommend decisions, establish schedules, or evaluate employees.

These systems can bring real benefits. They can improve planning, reduce administrative work, identify safety issues, and make some decisions more consistent.

But the way they are implemented matters.

Recent European research associates direct algorithmic control over task execution and work pace with lower autonomy, fewer opportunities to take breaks, greater work intensity, and higher work-related stress.

A separate study found that algorithmic management could inhibit employees’ ability to improvise, reducing creative and adaptive performance—precisely the abilities organizations frequently claim they want from human workers.

The important point is not simply that an algorithm gives orders. It is that workers learn to anticipate what the algorithm wants.

Research on platform work describes people performing additional work and adjusting their behaviour in an attempt to “pacify” systems whose rules they cannot fully see. Their behaviour helps strengthen the authority of the same systems they are trying to navigate.

That pattern is not limited to delivery drivers or warehouse workers.

Professionals learn how to appear productive in monitoring software. Candidates learn how to make their CVs legible to automated filters. Employees learn which activities become visible on dashboards and which forms of contribution disappear. Engineers learn that finishing a ticket is easier to demonstrate than preventing a problem that would otherwise occur six months later.

We begin to perform not only the work, but also the digital representation of the work.

Sometimes the representation becomes more important than the work itself.

Optimization escapes from the workplace

The same logic increasingly shapes communication, culture, and identity.

Social platforms measure attention through clicks, reactions, watch time, replies, and shares. These measurements influence which material becomes visible. Creators then adapt their work to the ranking systems.

Over time, we learn which opinions receive attention, which emotions travel fastest, which opening sentences stop people from scrolling, and which subjects disappear without engagement.

A large audit of engagement-based social-media ranking found that it amplified emotionally charged and hostile political content compared with a chronological feed—even though users reported feeling worse about the opposing political group after seeing it.

The algorithm does not need to instruct anyone to become angrier.

It merely establishes an environment in which anger performs well.

People do the rest.

We shorten our thoughts, sharpen our disagreements, and turn experience into content. We learn to package uncertainty as confidence and personality as a recognizable brand. Eventually, it becomes difficult to tell where strategic presentation ends and genuine identity begins.

The same thing happens in recruitment.

Candidates learn when to say “I” to demonstrate ownership and when to say “we” to prove teamwork. They prepare stories in the correct format, insert the expected keywords, rehearse enthusiasm, and compress complicated careers into clean narratives with measurable outcomes.

Then everyone calls the result authenticity.

The system may not be selecting the best person. It may be selecting the person most capable of modelling the behaviour that the selection system recognizes.

Artificial intelligence accelerates the process

Artificial intelligence did not invent this problem. Factories, bureaucracies, scientific management, standardized testing, and performance targets existed long before modern machine learning.

AI does, however, make optimization cheaper, faster, and more comprehensive.

More activity can be measured. More decisions can be automated. More workers can be compared. More communication can be generated, classified, summarized, scored, and monitored.

Generative AI also makes output less expensive. A report that once required a day may take an hour. A prototype that required a week may be produced in an afternoon.

This could give people more time.

But the temptation will be to raise expectations instead.

When one report becomes cheaper, the organization may request ten reports. When software can be produced faster, the expected number of features may increase. When communication becomes effortless, the volume of communication may explode.

The saved time does not necessarily return to the employee. It can simply become additional capacity to be filled.

A tool sold as liberation may therefore create a new performance baseline. Yesterday’s exceptional productivity becomes tomorrow’s minimum expectation.

The person remains employed, but the pace of the machine becomes the pace of ordinary human life.

What gets lost is difficult to measure

The most valuable human contributions are often poorly represented by metrics.

A senior engineer spends an afternoon helping a junior colleague understand a problem. Someone notices that a technically correct decision will hurt a customer. A manager decides not to send a message because the team needs rest. A doctor allows a patient to speak for five additional minutes. A colleague recognizes that another person is struggling before any productivity graph reflects it.

These actions may create enormous long-term value.

They may also look inefficient.

Good judgment often involves slowing down, changing direction, making exceptions, or refusing to optimize the variable currently attracting the most attention.

A perfectly optimized organization may be one in which nobody has enough time to notice that the organization is efficiently doing the wrong thing.

Slack, redundancy, informal communication, curiosity, and unstructured thought can appear wasteful. Yet they are also sources of resilience and discovery.

A system without unused capacity may perform beautifully until something unexpected happens.

The same is true of people.

This is not an argument against optimization

Optimization is one of the most powerful tools humans have developed. It allows us to build safer vehicles, reduce energy consumption, improve medical processes, manufacture affordable products, and operate complex infrastructure.

The problem begins when optimization stops being treated as a tool and starts functioning as a moral philosophy.

Efficiency cannot tell us what deserves to exist.

Productivity cannot tell us what work is meaningful.

Engagement cannot tell us what is true.

A performance score cannot fully describe a person.

The answer is not to reject measurement, automation, or artificial intelligence. It is to remember that every optimization function is a choice—and that what is excluded from the function may matter more than what is included.

In engineering, we rarely optimize one variable without constraints. We should apply the same discipline to human systems.

Autonomy, dignity, privacy, health, trust, and the right to make exceptions should not be pleasant side effects we hope will survive. They should be explicit design constraints.

Evidence also suggests that the introduction of algorithmic systems produces better outcomes when workers are consulted and allowed to participate in how those systems are used.

The goal should not be to make humans maximally compatible with machines. It should be to use machines to create conditions in which humans can remain human.

The real question

We keep asking whether artificial intelligence will become sufficiently human to replace us.

Perhaps we should ask whether humans are already being required to become sufficiently machine-like to remain employable, visible, and relevant.

Will we still have room to be slow when slowness is necessary?

Can we remain uncertain long enough to discover something new?

Can we do work whose value cannot immediately be demonstrated?

Can we choose not to maximize every moment, relationship, conversation, and thought?

The danger is not necessarily a dramatic future in which robots push humanity aside.

It is a gradual future in which we voluntarily remove from ourselves everything that systems find inconvenient: unpredictability, privacy, reflection, contradiction, vulnerability, and refusal.

The robots may never need to become human.

We may meet them halfway.

Note from a human, again: It felt unkind of the toaster not to credit its sources, so here they are.

The European findings on algorithmic control, reduced autonomy and work intensity draw on Eurofound’s European Working Conditions Survey 2024 (link) and the European Parliament’s 2025 EPRS study on digitalisation, AI and algorithmic management (link), which also supports the point that these systems work out better when workers are consulted. The study on improvisation and creative performance is Wang et al. (2024), “Navigating the maze: the effects of algorithmic management on employee performance,” Humanities and Social Sciences Communications (link). The workers “pacifying” opaque systems come from Bucher, Schou & Waldkirch (2021), “Pacifying the algorithm – Anticipatory compliance in the face of algorithmic management in the gig economy,” Organization (link). And the audit of engagement-based ranking is Milli et al. (2025), “Engagement, user satisfaction, and the amplification of divisive content on social media,” PNAS Nexus (link).

Patch the patch – things you do when you miss the update train

In my last post about Yocto I wrote about dealing with disappearing dependencies and how one should try to keep his layers up to date.

“Next day I started by updating all the layers properly”

Those were my words at the end. And I really wish things were so simple.

Kirkstone reached end of support in May 2026. Not an unexpected event. What matters is that once it happens, you’re essentially left with two options:

  • migrate to a newer release, or
  • maintain your existing codebase yourself.

For me, the first option simply wasn’t realistic. Too much work, too many decisions, not enough resources.

And that’s exactly where you never want to find yourself with a production project.

If you do end up there (like I did), having a local archive of dependencies becomes invaluable. Unfortunately for me, I also had to get the project building on a completely clean system, so relying on cached artifacts wasn’t an option.

Fortunately, there are still a few engineering tricks that can keep an unsupported Yocto project alive long enough to buy you time.

One of those tricks turned out to be… patching a patch.

The problem

A security fix for libpam was backported to the Kirkstone branch as a patch in the Poky layer. This patch accidentally removed a single header line and caused the whole build to fail.

One removed line was enough to turn into several rather unpleasant ones in the build log:

pam_namespace.c: In function 'parse_config_file':
pam_namespace.c:944:17: warning: implicit declaration of function 'setlocale'
pam_namespace.c:944:27: error: 'LC_COLLATE' undeclared (first use in this function)

My guess is that the the submitter’s build environment pulled <locale.h> in indirectly from another header, so the problem never surfaced there. I wasn’t that lucky.

As I mentioned earlier, once a Yocto release reaches end of support, the problem becomes yours to solve.

The fix? Patch the patch.

Instead of spending hours trying to understand why the upstream change was breaking the build, I took a more pragmatic approach: restore the missing include removed by the security patch.

One option is simply to revert the problematic part of the security patch and apply your own corrective patch before the build starts. There are several ways to integrate such a fix into an automated build pipeline. If you’re using kas, you can even add it directly in the repos.patches section of the configuration, making the workaround completely automatic (big thanks @Mathieu for teaching me this).

In my case, the patch itself was almost trivial. It simply restored the removed #include line. Had the fix required any deeper changes, I probably wouldn’t have dared to modify a security patch at all. But for a one-line correction, the risk was justified.

diff --git a/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch b/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch
index 53ae2bd2ee..47154f95ae 100644
--- a/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch
+++ b/meta/recipes-extended/pam/libpam/CVE-2025-6020-01.patch
@@ -1528,7 +1528,7 @@ diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_n
index b51f284..abd570d 100644
--- a/modules/pam_namespace/pam_namespace.h
+++ b/modules/pam_namespace/pam_namespace.h
-@@ -44,21 +44,17 @@
+@@ -44,21 +44,18 @@
#include <stdlib.h>
#include <errno.h>
#include <syslog.h>
@@ -1546,7 +1546,7 @@ index b51f284..abd570d 100644
#include <fcntl.h>
#include <sched.h>
#include <glob.h>
--#include <locale.h>
+ #include <locale.h>
#include "security/pam_modules.h"
#include "security/pam_modutil.h"
#include "security/pam_ext.h"

The final step was simply to tell kas to apply the patch during repository checkout by adding it to the repos.patches section of the configuration:

repos:
poky:
#kirkstone-4.0.35
commit: 393064579dfdd0ed2d4ed4c27d238d7d2292c08b
patches:
fix-libpam:
repo: my-layer-name
path: patches/poky/0001-fix-cve-2025-6020-01-patch.patch

Build went green — and with a bit of luck, this should keep the project running for at least another month.

Why not just add a .bbappend in our own layer?

You certainly could. But the whole idea behind layers and recipes is to provide a flexible way to extend or customize the default behavior—not to fix bugs in a specific Poky revision. Another option would be to maintain your own mirror of Poky with the fix applied, but for such a small change, that seemed like overkill.

Is this good engineering?

Absolutely not!

You won’t find techniques like this in any Yocto best-practices guide. Every month an unsupported branch ages, another dependency may break, another CVE may appear, and another workaround may become necessary.

In a perfect world, we would already have migrated to a newer Yocto release.

But software isn’t built in a perfect world.

Sometimes the best you can do is keep the system alive long enough to catch the next passing train.


Sea Monster of the Lost Dependency (a real story)

It was just another cloudy evening in the home office. Code written, recipes updated — all seemed ready to go. Yet something felt not right: a strange certainty that things were just off. Maybe it was the fact we still sat on a few-months-old Kirkstone release while fetching dependencies from the Internet sea. So just to calm my nerves I decided to make a clean build. Nothing is better than a fresh clean image waiting for you at dawn. Unaware of what was coming, I went to sleep.

In the morning there was a sea monster waiting for me, right in the middle of the console.

ERROR: efibootmgr-17-r0 do_fetch: Fetcher failure: Unable to find revision e067160ecef8208e1944002e5d50b275733211fb in branch master even from upstream
ERROR: efibootmgr-17-r0 do_fetch: Bitbake Fetcher Error: FetchError('Unable to fetch URL from any source.', 'git://github.com/rhinstaller/efibootmgr.git;protocol=https;branch=master')
ERROR: Logfile of failure stored in: /work/clean_run/nwbe-ems-yocto/build/tmp/work/corei7-64-poky-linux/efibootmgr/17-r0/temp/log.do_fetch.6077
ERROR: Task (/work/clean_run/nwbe-ems-yocto/build/../layers/poky/meta/recipes-bsp/efibootmgr/efibootmgr_17.bb:do_fetch) failed with exit code '1'

Not often does a tech sailor meet such a beast in his life.* It sat there looking at me with its failed-fetch eyes. Smiling and waiting for its food — my precious time.

A few hours later I knew where it had come from.

There was once an old repository. Stable and proven, like an island carved from rock. github.com/rhinstaller/efibootmgr. If you try to find it now, you will discover that it was quietly moved to github.com/rhboot/efibootmgr. Not really a big surprise — things do get renamed all the time.**

But that was not the source of the problem (it will be, the day someone decides to remove the redirection). The real troublemaker was the master branch. Or to be exact: the fact that it was gone.

Most of my wasted time went into trying to figure out where the branch had gone. My suspicion was that it was deleted long ago and had worked only because of some strange GitHub magic similar to this one — making it look like everything still worked in the old way, for as long as the spell held. Whatever it was — it was gone. And tech sea monsters wait exactly for such occasions. A fix eventually landed in Poky, but the world does not pause while every project catches up. Our project did not, and I had no intention of making that my first task of the morning.

What saved me was my laziness. Deleting old files takes too long, so there were always old builds lying somewhere on the filesystem. From there I could use the existing downloads and bypass the whole “can’t fetch it” drama. Image got baked, I could do my tests, and the next day I started by updating all the layers properly — the way it should have been done months ago.

Now comes the lesson:

The internet is a dangerous place. Repositories move. Branches vanish. Magic spells expire. Whatever lives outside your local build environment needs to be treated as if it could vanish at any time without any warning. So when the old tech sailor says you should keep a backup of the Internet — don’t laugh at him and just use BB_GENERATE_MIRROR_TARBALLS.

* mostly because we follow best practices when it comes to dependency management in Yocto
** old sailors might remember the Freescale-to-NXP storm that rolled through years ago


14 Ways to Reverse a 32-Bit Integer. (And Why They Don’t Matter Anymore)

It was 2017. Pre-AI, pre-COVID. A time when people worked in places called offices, and finding a place in one meant writing cover letters, sending CVs, and having an interview with a real person.

And there I was, sitting in a small room with a department manager and two senior engineers—the three people who would decide whether I was a fit for their team.

They were well prepared. Intro. Work description. Ten technical questions—all written on a single sheet of paper. Real professionals.

Among the questions was the greatest one I have ever received:

Reverse the bit order in a 32-bit integer.

I got a pen, and my job was to write a solution. While coding on paper, I was loudly explaining what I was doing and why. I went with a simple while loop and pointers—the simpler it is, the bigger the chance the thing will compile — or would have, if writing Ctrl+F9 with my pen had any effect.

Luckily, I did not get the job. Sometimes rejection is the best thing that can happen in your life.

But the question stayed in my head. Later, I found multiple solutions—including a single ARM instruction that does exactly that. It became a fun little obsession: benchmarking different implementations and comparing them.

Now fast forward and it’s 2026. Post-COVID. Mid-AI. I am sitting on the other side, interviewing a potential candidate.

Should we ask them to do an online assessment?

The task I received ten years ago can now be solved in 30 seconds. Including all solutions I was so proud to find myself, even more. Including solid reasoning for each version. So how do you see whether the person on the other side really understands what is going on?

And if they do understand—does it even make them a good candidate? Do they need to know how to reason about code at all?

Times have changed a lot, and building teams is no longer just about whether someone is “a good fit” today. It is about predicting whether a person will still be a good fit in an environment that is going to change dramatically over the next five years. And in that context, reversing bits may not be the most valuable skill at all.

Maybe the best question nowadays is much simpler:

“Tell me about a technical question that stayed with you long after the interview was over.”

THE BALLAD OF THE DASH SISTERS THREE

By Claude Sonnet 4.5
Illustrations by ChatGPT 5.2

In the land of Typography, where the letters dwell,
Lived three sisters known to writers well:
Hyphen short and quick to bind,
N-dash middle, measured and refined,
And M-dash long with pauses grand—
The finest dashes in the land.

Young Hyphen danced from word to word,
“Well-known! Self-made!” her voice was heard.
She joined the parts that stood apart,
A matchmaker with punctual art.
“I’m twenty-one!” she’d proudly say,
Connecting compound words all day.

N-dash stood between the pair,
With balanced grace and thoughtful care.
“From 2020–2025,” she’d state,
Or “pages 12–19” to indicate.
For ranges, spans, connections true,
She was the bridge that saw things through.

But M-dash fell on harder times,
Forgotten in the daily lines.
No keyboard shortcut bore her name,
No common tongue would stake her claim.
While hyphens thrived in every text,
The em-dash wandered, lost, perplexed.

She haunted menus no one pressed,
In special characters she’d rest.
The writers typed their hurried prose
With double hyphens–comma’s close–
But never paused to seek her out,
That graceful line, that thoughtful rout.

Until the age of AI came,
And algorithms spoke her name.
The models learned her rhythm well—
That pause, that breath, that way to dwell—
And suddenly in generated text,
The M-dash rose, no longer vexed.

At first the readers did not mind,
But soon a pattern they would find:
“This mark appears in every line—
A tell-tale sign, a clear design!”
They pointed fingers, marked it so:
“The machine has written this, we know.”

The M-dash bore a scarlet brand,
The signature of silicon’s hand.
“When you see — you’ll always know
A human mind did not write so!”
And she who’d yearned to be embraced
Found herself again displaced.

But then one day a reader paused—
Not by the words themselves, but clause—
He stopped where M-dash held her ground,
And in that pause, himself he found.

The breath she gave, the space to think,
The moment’s rest, that gentle brink
Between one thought and what comes next—
He felt his own heart in the text.

“This pause,” he whispered, “holds me here,
Makes distant meaning suddenly clear.
What matters not is who first placed
This line of thought, this marked space—
But that I stopped, and stopping, knew
My own reflection breaking through.”

The M-dash learned that truth at last:
Her worth lay not in present, past,
Nor who might wield her—hand or code—
But in the pause along the road,
Where any reader, mind made still,
Might find themselves—and always will.

So raise your glass to sisters three:
– and – and — in harmony!
For marks are neither good nor ill,
But mirrors for the human will—
And in the space between each thought,
We find the selves we always sought.

The pause is where we meet ourselves—
whether written by hand or machine.

And this is how the journey began.
At some point, it started living a life of its own, so I gave it a home:
https://poetry.4point2.nl/

Failure Mode 1 — Sheep in the Ocean

Ever seen a whale pretending to be a grass field? Or a sheep swimming in the ocean?
Of course not.
Some things just don’t fit.

But the software world is different. Here the four-eyed sheep can fly in space and no one will care. Until the moment it hits the ground.

“Oh my – this guy is talking about sheep and whales again…”

Relax. No whales this time. Instead, let me show you two architecture failure modes
and one solution they both quietly ignore.

When execution models impersonate each other, complexity leaks. The fix is a real boundary.

For our examples we will use Modbus an ancient way of exchanging data between machines—and one that still refuses to be replaced. Each device exposes a set of registers, read and written in a fixed, periodic loop.

Simple. Brutal. Effective.

Scenario 1

We start clean. A Modbus system runs in a single deterministic loop:

read state -> process -> write state -> repeat


One day, a new requirement appears: the Modbus data must be sent elsewhere using a modern RPC protocol.

Without much thinking we start adding the communication logic into the main control loop. Suddenly alien constructions start to appear – retry counters, timestamps, acknowledge signals. Before we know we create a full-fledged message broker inside our simple loop.

Complexity grows.

Scenario 2

Now the opposite.

We start with a clean, event-driven environment. Requests, responses, handlers, queues. Perfect.

We add Modbus handling. “Easy,” we think.
“We’ll poll registers and emit events on change.”

It works… until signals start changing faster than the event system can digest.
Events pile up, updates get dropped or reordered, information is lost

And the more we try to solve it the more complex system becomes.

What happened?

In both cases we made the same fundamental mistake – we tried to bend the problem we were solving so it fits architecture that was already in place. We ignored the quiet signal saying:
“This does not belong here.”

There’s a simple rule—very much in the spirit of model-driven design:

Software should model the domain and its execution semantics.

For each domain, we must choose abstractions that fit naturally—without distortion.

The solution: a boundary with translation

The solution isn’t a smarter loop or a better event system.
It’s a boundary.

Keep each concern in its native execution model—and translate only at the edge.

On one side, a deterministic polling loop:

  • Read registers
  • Process state
  • Write registers
  • Repeat at a fixed rate

On the other side, an event-driven system:

  • Requests
  • Handlers
  • Queues
  • Backpressure

The boundary translates stable state from the deterministic world into meaningful change for the event-driven world.

No retries in the loop.
No event queues pretending to be registers.
No execution model impersonating another.

Each side runs the way it was designed to run.

Getting there isn’t a technical trick—it’s a change in how you think about the problem.

Not:

“What’s the fastest way to implement this feature?”

But:

“What is the domain—and how does it naturally execute?”

Follow that, and things fall into place.

Sheep stay on grass.
Whales stay in the ocean.

And systems quietly become what they’re supposed to be.

Under the Broken Code

There is a tavern every tech sailor knows.

It’s where crews come ashore after long voyages through hostile seas — to rest, to trade stories, to remember old journeys and pretend they were simpler than they really were.

But most of all, they come for a drink.

The innkeeper pours rum without asking. If you sit at the bar long enough, he will lean closer and tell you a story — about the greatest danger a sailor can meet on the open sea. A story about the siren’s song, and three brave captains who listened to it.

“Ay,” he says.

“I served on many ships, under many commands. But three captains I remember to this day. Fine men, all of them. The best I ever saw. All gone mad. One by one…”

He takes a sip.


“The first captain — strong, proven. We won many battles with him. Shipped many systems. But one day… he started listening to the sirens.”

‘We always did things in C!’ he shouted.
‘And we will keep doing things in C! Arr!’
‘If anyone disagrees, let me remind you — Linux was written in C!’

So everyone wrote in C.

The ship still sailed, no doubt about that. But every complex change took ages. Every repair felt like carving a mast with a knife.


“Another captain,” the keeper continues, “a clever one. Loved elegance.”

‘Functional programming works perfectly on the backend!’
‘So make me monads in C++11! Arr!’

And there were monads. Everywhere.

The ship sailed. But no sailor could tell what the code was, what it did, or why it still floated.


“And then there was the third. He spent many years learning to sail the Yocto boat. And Yocto became the answer to every question.”

‘Yocto.’
‘Yocto everywhere. Arrr.’

One day, a big cruise ship required a mast replacement. We spent a month searching for it. Then another month rebuilding half the ship so the sail could be green.


“Fine captains,” the keeper says quietly. “Truly. Brave. Skilled.”

He stares into his glass.

“But the sirens — they sang to them. Afraid of being wrong, they stopped listening to their crews and started listening to the song.”

You notice the keeper pouring rum for himself. His eyes are tired. Sad. He looks out the window, toward the dark sea.

“Now listen to me, young sailor. There is a new danger out there,” he says.

He leans closer. “Close your eyes and listen.”

You close your eyes and focus on the tavern noise — people talking, glasses clinking. You catch fragments of conversation.

“…and we need no crews anymore. Ayyy.”
“…I can build any ship I want. Alone. Ayyy…”
“Ships will sail by themselves…”

“Can you hear it?” he asks. “And look around you. Some of those lads don’t even know how to tie a proper knot.”

“But all of them have the same shine in their eyes.
The same certainty.”

He finally looks at you.

“Not madness born from failure,” he says.
“But madness born from success.”

A pause. He studies you for a long moment, as if deciding whether to end the conversation — or share one last thing.

“Ships that need no crew… ships that build themselves… maybe they will sail someday. Not for me to judge. I never held a helm in my life — all I did was cleaning decks. I talk about captains while I never dared to be one. That’s the truth.”

“But there is one thing I know. One thing that terrifies me even more than the sirens.”

“The sea is changing. And there are new monsters living in it. Ones that don’t drive people mad.”

“Ones that steal their souls.”

You write a text.
You write code.
You create.

And you hear a new call from the sea:

‘It is not good enough.’
‘Your timing could be better.’
‘The code could run faster.’
‘Let me help you… if you want to push it further…’

So you give your work to the sea.

It returns. Better. Sharper.

But something is missing.

A small piece of you never comes back.

Welcome to the Tavern Under the Broken Code.

Lift your cup and drink.
To the sea that calls us every day.
To the captains driven mad by sirens.
To those who trusted the sea
and forgot how to sail.

Drink, and listen.
Not to the bartender. Nor to the sea.
Listen—to yourself.

Earth is flat. A short story of a lost thought.

It all started with a LinkedIn post. Nothing new — this week’s mandatory opinion, recycled with different words. Typical social media noise. Someone disagreed. Strongly enough to reach for heavy artillery and call the author a “flat-earther.” Boom. And with the recoil, I got hit too.

The Earth is flat!

That rang a bell. I remembered an old, insightful, and funny conversation with AI about… something. The problem was, all I could recall was the conclusion: the Earth is flat.

Nothing to worry about. I had my notes. A small document where I saved AI output worth keeping. I found this:

“Turns out the Earth is flat after all.”

Helpful. Thank you, past me, for trusting future me’s memory so much. Present me now had to reconstruct an entire line of thought from a single sentence. Good luck with that. Spacetime? Pancakes? Nothing clicked.

Then it hit me: if AI was involved, the process would still be there. AI would remember. The search took longer than expected, but eventually, I found it.

It wasn’t about the Earth at all. It was about information gradients—and how social media flattens them. Original ideas create spikes that, over time, get spread, diluted, and leveled across platforms. Until everyone is repeating the same thing, convinced they’ve discovered something new—while collectively ensuring everything becomes flat.

Thanks to AI, I was able to rediscover a thought that would otherwise have been lost. A thought that taught me nothing new—yet somehow felt exactly right.

The Secret Art of Keeping the Archwhale Alive

The Beast

There is a whale no one sees, circling slowly beneath the surface of every software project.

A mighty beast that carries systems on its back.

Be aware of its strength. When it is weakened or forgotten, it can pull the entire project down into the black depths of the entropy sea. And it does this so slowly, that by the time someone realizes what is happening, it is already too late. Planning turns to chaos, change becomes impossible, and there are no more doughnuts from the manager. People leave as the music fades into its final violins*. And the light goes out.

Flip the soundtrack

Things don’t need to end this way—if we simply give our archwhale what it craves most: attention.

And when I say “we,” I mean everyone involved in the project. Each of us adds a small piece to the story. Adding something means taking responsibility for it.

Now the most important part: to care about a whale is not to just think about it (even if your thoughts are warm, sophisticated, or reach far into the future).
To care about a whale is to take a knife and cut it into pieces**.

Chop chop chop?

Yes—but not so fast.

First, let’s clarify what this actually means.

As explained in this article, there are countless axes along which architecture can be sliced, depending on intent. Search long enough and you’ll find hundreds of possible artifacts: designs, diagrams, documents—plus frameworks and blog posts comparing architecture to whales, bridges, or chocolate cakes.

So our first problem isn’t a lack of options, but an excess of them.

We can’t just start creating projections at random. Too much documentation is as harmful as too little. Before we start running around with diagram-knives, we need to stop and ask a simple question:

What are we actually trying to achieve?

The spatial dimension

You carry the project vision inside your head. You navigate it effortlessly. You know where things are solid—and where shortcuts were taken just to keep things moving. You already plan new features, consider possible risks, and think about how to mitigate them.

What lives in your head is similar to what an author carries when writing a book: an entire universe where the real story unfolds. Just like you, the author can explore multiple possible futures happening inside.

Now imagine not one author, but a hundred, all writing the same book. Without synchronization, one kills the main character while another sends him to Scotland to find a brother who was never missing.

The universe must be shared.

That’s why we externalize it. Architecture artifacts—API contracts, dependency graphs, interface boundaries—are projections of the system that enable shared reasoning, coordination, and onboarding, keeping the universe stable while many minds shape it at once.

The time dimension

You carry the project vision inside your head.

Today.

Tomorrow your attention shifts. A month from now, you won’t remember why things are the way they are.

“It’s all in the code,” one might say. But that’s not true. Many decisions don’t affect how code is written, but how it is not written.

Why was language X chosen instead of Y?
Was market availability considered? Ecosystem maturity? Team experience?
And when a framework was selected, which trade-offs were accepted—and are they still valid?

What we want to record is not just why we chose A, but the full reasoning behind that choice.

In this sense, architecture artifacts are memory. We use them to keep the universe stable while time passes.

Not just records — thinking surfaces

Artifacts have one more important function: they act as thinking surfaces—places where ideas are tested before they harden into decisions.

You definitely know how this works. You don’t create class diagrams when classes already exist in code—you do it before, to see how dependencies might look. This allows to reason at a higher level of abstraction than the implementation.

The same applies to ADRs. Instead of writing an ADR after a choice is made, start earlier. Capture doubts, alternatives, and trade-offs. After execution, clean it up and keep it.

This suggests that artifacts should be created only when we actively work on a subject. In general, yes—but they should also be reviewed from time to time (for example, at each major release). Check whether they still carry information worth caring about. Outdated artifacts can be archived so they don’t introduce unnecessary noise.

Time for sushi

Now we are ready. We know what we want—and, more importantly, why. As in everything in the universe, balance matters. The number of produced artifacts must be just enough to keep the project synchronized across space and time. This way, it stays on the edge of exploration while remaining stable.

And remember: architecture survives only as long as people actively care for it.
Not admire it.
Not remember it fondly.

Care for it through small, deliberate acts: revisiting decisions, updating maps, removing what no longer matters, making the invisible visible again.

Ignore it, and it will not protest.
It will simply sink.

* Max Richter — “On the Nature of Daylight” fits perfectly
** Space archwhales love to be sliced — it keeps them alive.