<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://xn--izc.com/">
  <title>The Letter අ</title>
  <subtitle>Strong opinions weekly held</subtitle>
  <link href="https://xn--izc.com/feed.xml" rel="self" />
  <link href="https://xn--izc.com/" />
  <updated>
    2026-02-15T00:00:00Z
  </updated>
  <id>https://xn--izc.com/</id>
  <author>
    <name>Asanka Herath</name>
    <email>asanka@gmail.com</email>
  </author>
    <entry>
      <title>Something Happened On The Way To Perfect History</title>
      <link href="https://xn--izc.com/posts/perfect-information/" />
      <updated>2026-02-15T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/perfect-information/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;In the wee hours preceding dawn of the 29th of June, 3123 BCE, a
Sumerian astronomer looked up at the night sky and recorded the
trajectory of a large object. The object is believed to have been over a
kilometer in diameter (about 11 football fields). Its impact is known as
the Köfels event whose aftermath included a 900km high ejecta plume, a
500m thigh debris layer, and climate change.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/perfect-information/tablet.jpg&quot; class=&quot;noinvert&quot; alt=&quot;The Cuneiform tablet in the British Museum collection No K8538 (known as “the Planisphere”). © The Trustees of the British Museum. Shared under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) licence.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The Cuneiform tablet in the &lt;a href=&quot;https://www.britishmuseum.org/collection/object/W_K-8538&quot;&gt;British
Museum collection No K8538&lt;/a&gt; (known as “the Planisphere”). © The
Trustees of the British Museum. Shared under a Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
licence.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Roughly 5147 years&lt;a href=&quot;https://xn--izc.com/posts/perfect-information/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; later, the security cameras at a
home near Charlottetown, Prince Edward Island (PEI), Canada, captured
the first sight and sound of a meteor striking Earth. The footage is of
substantially higher fidelity than the Cuneiform tablet. The sea of
discussion, scientific research, new reports, and social media activity
surrounding this event makes it irrefutable.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/perfect-information/meteor-strike.jpg&quot; class=&quot;noinvert&quot; alt=&quot;A mark left in the walkway where the meteor struck in July, 2024 outside Laura and Joe Kelly’s house in Prince Edward Island, Canada. The meteor is substantially smaller than the 1km wide Köfels meteor. Image Source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A mark left in the walkway where the
meteor struck in July, 2024 outside Laura and Joe Kelly’s house in
Prince Edward Island, Canada. The meteor is substantially smaller than
the 1km wide Köfels meteor. &lt;a href=&quot;https://skyandtelescope.org/astronomy-news/hear-the-first-ever-recording-of-a-meteorite-slamming-into-the-ground/&quot;&gt;Image
Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The Era of Perfect History is the period in human history during
which every pertinent detail of even minor events would have
photographic or video evidence. We are not there yet, and it’s likely
that we never will.&lt;/p&gt;
&lt;p&gt;Imagine billions of people running around with high-definition
cameras that they can pull out and record at a moment’s notice. And now
imagine there are dozens of social networks that reward sharing footage
of any notable event with an audience of millions, and the fame and
glory that come with it. This sounds exactly like where we were heading,
doesn’t it?&lt;/p&gt;
&lt;p&gt;No government would be able to lie to its citizenry. Every misstep or
misstatement would be backed by irrefutable evidence. Just as the
internet was supposed to bring about a perfectly informed society, with
unfettered access to the truth, a history of perfect information was
also supposed to bring about a just and transparent society, one where
everyone can be held to the truth… eventually. However, some argue that
the sheer volume of information could lead to manipulation,
misinformation, and erosion of trust. The optimists’ view of perfect
information bringing about a just society might overlook the
complexities of human behavior and societal dynamics. Nobody planned
this, but it was just the direction we were heading as a species.&lt;/p&gt;
&lt;p&gt;The past couple of years changed many things, one of which is the
irrefutability of video or photographic evidence. As of this writing, it
is no longer possible to reliably tell AI-generated imagery from
“authentic” imagery. (&lt;a href=&quot;https://www.ted.com/talks/hany_farid_how_to_spot_fake_ai_photos&quot;&gt;E.g.&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;It is frightening how scarce reality is compared with what can be
synthesized. Intuitively, it may seem to be the other way around. After
all, our capacity to simulate reality is vastly inferior to reality
itself. The discrepancy comes from the volume with which generative
content can be injected into our discourse. While we labor for hours
making squaking sounds with our throats or poking plastic with our meat
sticks, generative content can spit out a million articles. As &lt;a href=&quot;https://gijn.org/resource/guide-detecting-ai-generated-content/&quot;&gt;Henk
van Ess&lt;/a&gt; says, “traditional fact-checking takes hours or days. AI
misinformation generation takes minutes.”&lt;/p&gt;
&lt;p&gt;Hoaxes and conspiracies abound, but so far we haven’t seen a
substantial historical event be completely synthesized via AI. Either
that or the falsehood was so perfectly executed that nobody can
tell.&lt;/p&gt;
&lt;p&gt;It would make for a great science fiction story until it actually
happens.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;… and 26 days to be exact. It is kind of incredible how
people came up with such an accurate estimate. I haven’t read the book,
but if anyone could have a look at chapter 4 and tell me, that would be
great. In the meantime, I’ll have to take the word of &lt;a href=&quot;https://www.bristol.ac.uk/news/2008/212017945233.html&quot;&gt;the
University of Bristol&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/perfect-information/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>False Precision and Vibe Coding</title>
      <link href="https://xn--izc.com/posts/false-precision/" />
      <updated>2026-02-13T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/false-precision/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It occurs to me how much of human communication is
disambiguation.&lt;/p&gt;
&lt;p&gt;We have short lives and shorter attention spans. So we have to be
tactful about fitting in just enough detail into the brief blips of
attention that we are afforded. We wouldn’t enjoy listening to
protracted descriptions of things we already know. So we fast-run along
a stream of concepts where we only lay down just enough track for people
to keep up.&lt;/p&gt;
&lt;p&gt;We narrate things.&lt;/p&gt;
&lt;p&gt;We tell stories, episodic journeys with familiar names and places and
little else other than dialogue and the occasional pantomime. We convey
so little detail, but for the right audience, the story is as vibrant,
colorful, and detailed as anything from their own sensory
experiences.&lt;/p&gt;
&lt;p&gt;Things unsaid are those that don’t need saying. The listeners know
how to fill in the gaps.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Effective communication requires knowing how to balance what to say
and what to leave out —either because it is a detail that is unambiguous
or because it’s an intentional gap that we want the listener to
fill.&lt;/p&gt;
&lt;p&gt;Programming, at least the “classical” kind, does not afford us this
luxury. Everything has to be laid out precisely and in detail; even when
those irrelevant details. So we seek the comfort of layer after layer of
abstraction that hides details we don’t want to see. The same
abstractions alleviates us of the responsibility of saying what we don’t
need to say.&lt;/p&gt;
&lt;p&gt;We hope that, much like our human conversation partners, the computer
would fill in the gaps predictably and reliably. We hope it will do what
we mean, not what we said. We are disappointed, frustrated, and
occasionally amused when reality surprises us.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Software is a description of a machine.&lt;/p&gt;
&lt;p&gt;Software is only useful when something interprets it and actualizes
the machine. Actualizers –a.k.a. computers– aren’t smart. Every layer of
a computer system needs to be told what exactly it is supposed to do.
There cannot be any guesswork. So the description of the machine must
contain excruciating detail, because the computer that actuates it has
no ability to fill in the blanks.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/false-precision/false-precision.png&quot; alt=&quot;Vaguely understood problem + False precision ⟶ Precise and detailed solution&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Vaguely understood problem + False
precision ⟶ Precise and detailed solution&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We start with a vague understanding of the problem space. But
somewhere along the way, we have to inject it with false precision so
that the description becomes complete.&lt;/p&gt;
&lt;p&gt;This is why so much of modern software is based on false precision—at
least when it comes to end-user-facing systems. We are forced to
describe a behavior in rigid detail despite our incomplete understanding
of the problem space or lack of desire to overspecify the wrong
solution. The precision we inject becomes part of the solution, and in
large systems, indistinguishable from pertinent details. Sadly, our
descriptions of machines rarely allow us to demarcate necessary
precision and unnecessary precision.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Until now, that is. Finally, we have something that can take an
incomplete, vague description of our machine—stated in terms of what it
does or what its effect should be on something: &lt;strong&gt;vibe
coding&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Or to be more specific, &lt;strong&gt;vibe coding
specifications&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/false-precision/vague-specification.png&quot; alt=&quot;Vaguely understood problem ⟶ Equally vague specification ⟶ &amp;lt;AI Actuator&amp;gt; ⟶ Precise and detailed solution&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Vaguely understood problem ⟶ Equally
vague specification ⟶ &amp;lt;AI Actuator&amp;gt; ⟶ Precise and detailed
solution&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Our final actuators are still brute-force stupid. But at least now we
have something between us and the actuator that can fill in these pesky
gaps and again allow us the luxury of ambiguity.&lt;/p&gt;
&lt;p&gt;Ambiguity allows us to be earnest in our imperfect understanding of
the problem. We didn’t understand the problem because we have no perfect
understanding of the messiest, most important part of the
problem—&lt;strong&gt;us&lt;/strong&gt;. But now, finally, we can state our problem
the way we see it: vaguely and imprecisely.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>The Increasingly Inaccurately Named User-Agent</title>
      <link href="https://xn--izc.com/posts/user-agents/" />
      <updated>2026-02-09T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/user-agents/</id>
      <content xml:lang="en" type="html">
        &lt;aside class=&quot;sidenote-1&quot;&gt;
The title is a reference to the five-volume &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy&quot;&gt;Hitchhiker’s
Guide to the Galaxy&lt;/a&gt; series by Douglas Adams. The fourth and fifth
volumes in the series list themselves as being part of &lt;q&gt;the
increasingly inaccurately named Hitchhiker’s Trilogy.&lt;/q&gt;
&lt;/aside&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;The User-Agent, a technical name for the web browser, was supposed to
be our loyal butler on the internet – doing our bidding and keeping us
safe. But over decades, browser makers diluted its role, sometimes as a
result of actions done with the best of intentions. Both the internet
and browsers have become increasingly complex. And with that complexity,
the custodianship of the users’ data has become murkier.&lt;/p&gt;
&lt;p&gt;Despite being the one peddling our data, user-agents can no longer
tell us exactly who knows what about us. We’ve lost our agency over our
browsing data. And now our dude on the internet is a
&lt;em&gt;“user-agent”&lt;/em&gt; in name only.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We will soon have to confront an objectively more chaotic creature –
an AI-powered &lt;strong&gt;personalized&lt;/strong&gt; user-agent.
&lt;em&gt;Personalized&lt;/em&gt; meaning it knows a lot about us and will continue
to learn about us. &lt;em&gt;User-agent&lt;/em&gt; meaning it will take actions on
our behalf. And, &lt;em&gt;AI-powered&lt;/em&gt; at this point means that nobody
really knows how it works. Let’s talk about what is about to happen and
how you can prepare.&lt;/p&gt;
&lt;h3 id=&quot;the-user-agent-is-supposed-to-be-your-buddy.&quot;&gt;The User-Agent is
supposed to be your buddy.&lt;/h3&gt;
&lt;p&gt;Information is intangible – you can’t stick your finger in it. So
whenever we want to interact with a system that processes information,
especially of the digital kind, we need some stand-in for our finger so
that we can poke things.&lt;/p&gt;
&lt;p&gt;So, people came up with the concept of a &lt;strong&gt;user-agent&lt;/strong&gt;
– to refer to the device&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; that people interact with. People
would push buttons, make holes in paper, turn knobs, or do whatever they
need to do to communicate with the user-agent. The user-agent grasps
what the person wants, and does what it needs to do to make the person’s
wish a reality. On the flip-side, the user-agent also communicates
results back in a form that the person can understand.&lt;/p&gt;
&lt;p&gt;Early user-agents were simple creatures with no intent of their own.
It wasn’t that hard for people to look inside them to understand what it
was doing. There was no mystery. The user-agent did what was asked, and
earnestly reported back on what happened.&lt;/p&gt;
&lt;p&gt;For example, in an email system, this user agent is called a mail
user agent &lt;abbr&gt;MUA&lt;/abbr&gt;. A user-agent that interacts with the web on
our behalf should be called a web user agent (&lt;abbr&gt;WUA&lt;/abbr&gt;)&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;. But because web user agents —which
you might refer to as web browsers— are so dominant, people dropped the
superfluous “web” part.&lt;/p&gt;
&lt;figure&gt;
&lt;pre class=&quot;man&quot;&gt;&lt;code&gt;MUTT(1)                     User Manuals                    MUTT(1)

NAME
       mutt - The Mutt Mail User Agent

SYNOPSIS
       mutt [-hNpRxZ] [-s subject] [-c cc-addr] [-a file] ...
            [-F rcfile] [-H draft] [-i include] [-f mailbox]
            [address] ...

DESCRIPTION
       Mutt is a small but very powerful text-based MIME mail client.
       Mutt is highly configurable, and is well suited to the mail
       power user with advanced features like key bindings, keyboard
       macros, mail threading, regular expression searches and a
       powerful pattern matching language for selecting groups of
       messages.

       &amp;quot;All mail clients suck.  This one just sucks less.&amp;quot;
       - me, circa 1995&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
An ancient &lt;em&gt;“manual page”&lt;/em&gt; for the Mutt email client circa 1995.
Note that the program is described as &lt;q&gt;The Mutt Mail User Agent&lt;/q&gt;.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This was fine and dandy. People would fire up their user-agents, type
commands, and the user-agent would do stuff and show the user results.
But over time, these user agents evolved from simple command-line tools
to much more fancy interactive, graphical browsers and services. Modern
(&lt;em&gt;web&lt;/em&gt;) user agents are not just programs, they are entire
platforms&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;modern-user-agents-are-technical-marvels.&quot;&gt;Modern User-Agents
are technical marvels.&lt;/h3&gt;
&lt;p&gt;Since the same internet needs to be accessible from different
user-agents for perpetuity, the way web pages are written and made
available on the internet had to be standardized – i.e. everyone needed
to agree on the how. But these &lt;em&gt;technical specifications&lt;/em&gt;, or
&lt;em&gt;standards&lt;/em&gt; grew bigger and bigger and so demanding that only a
few well-resourced tech companies can write and maintain a full-featured
UA&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn4&quot; class=&quot;footnote-ref&quot; id=&quot;fnref4&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Though voluminous, these standards are neither perfect nor complete.
But they have been crafted through person-millennia of effort to ensure
security and correctness. Organizations like the following work
tirelessly to get the details right:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;World Wide Web Consortium&lt;/em&gt; (&lt;abbr&gt;W3C&lt;/abbr&gt;) is primary
group that governs how web content is written.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Web Hypertext Application Technology Working Group&lt;/em&gt;
(&lt;abbr&gt;WHATWG&lt;/abbr&gt;) is the group that pushes the boundaries of what is
possible to do inside the confies of a web browser.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Internet Engineering Task Force&lt;/em&gt; (&lt;abbr&gt;IETF&lt;/abbr&gt;) is the
group governing how data moves about on the internet, and also how to
keep your content secure while it is being moved about.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;The Unicode Consortium&lt;/em&gt; is responsible for which letters and
symbols you can use on the internet. They are the people who bring you
new emoji every year.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;… and many others.&lt;/p&gt;
&lt;h3 id=&quot;but-they-are-bound-by-the-same-implicit-social-contract&quot;&gt;But
they are bound by the same implicit social contract …&lt;/h3&gt;
&lt;p&gt;Beyond technical requirements, there is an increasingly important
social contract: That the user-agent always act on behalf of the
user.&lt;/p&gt;
&lt;p&gt;That means that the UA should do what you ask, and generally not do
what you don’t ask.&lt;/p&gt;
&lt;p&gt;The latter –don’t do what the user didn’t ask– is a little
complicated because of all the complexity involved in the modern
web.&lt;/p&gt;
&lt;p&gt;Say you ask to see &lt;code&gt;bank.com&lt;/code&gt; which is a bank. So the UA
talks to the &lt;code&gt;bank.com&lt;/code&gt; server and asks for the contents of
the page. The contents say that some of the pictures on the web page
need to be fetched from &lt;code&gt;advertiser.com&lt;/code&gt;. But doing so
involves sending a bunch of information to &lt;code&gt;advertiser.com&lt;/code&gt;
like the fact that you are viewing &lt;code&gt;bank.com&lt;/code&gt; and information
like your preferred language and whether you’ve been to these sites
before.&lt;/p&gt;
&lt;p&gt;Pretty much all UAs will opt to fetch the resources from
&lt;code&gt;advertiser.com&lt;/code&gt;, because otherwise the &lt;code&gt;bank.com&lt;/code&gt;
site will not work correctly. Since the user requested to see
&lt;code&gt;bank.com&lt;/code&gt;, clearly they intended for all the required stuff
to get downloaded too, right? Except, it’s likely that the user never
intended for &lt;code&gt;advertiser.com&lt;/code&gt; to learn all that information
about them.&lt;/p&gt;
&lt;h3 id=&quot;that-the-user-agent-must-act-only-on-behalf-of-the-user.&quot;&gt;That
the User-Agent must act ONLY on behalf of the user.&lt;/h3&gt;
&lt;p&gt;Herein lies the problem.&lt;/p&gt;
&lt;p&gt;The modern web is a marvel in that it exists despite brutally
conflicting interests, and is run by people who do not trust each other
one bit&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn5&quot; class=&quot;footnote-ref&quot; id=&quot;fnref5&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do you really think the nice lady who made you read her life story
before she told you how to make simple pancakes also made an ad for
weight loss drugs? Of course not.&lt;/p&gt;
&lt;p&gt;Behind the scenes, a “modern” web page is a warzone where multiple
companies are playing tug of war with your data and limited attention
span. Not only are these companies clamoring to show you video ads while
you are trying to make pancakes, they are also trying to figure out
where you’ve been and what you are into.&lt;/p&gt;
&lt;p&gt;You, the user, don’t want any of that; not even the nice lady’s life
story. You just want to make pancakes. A UA that acted &lt;em&gt;only&lt;/em&gt; on
your behalf would have just pulled out the recipe part and shown it to
you.&lt;/p&gt;
&lt;p&gt;In the short term, rewriting the web like this sounds great. But in
the long term, those companies – who now have no one to show ads to –
will stop paying the nice lady. And the nice lady will stop publishing
her recipes. No ads, no recipes&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fn6&quot; class=&quot;footnote-ref&quot; id=&quot;fnref6&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So to keep the web open, the UA does a tricky balancing act between
conflicting interests; one that is not weighed 100% on your behalf. The
UAs do their level best to present you with the most authentic web,
while trying to keep you safe from potential attackers, without
divulging too much about you to strangers. But this situation does mean
that the “user agent” isn’t truly just the user’s agent.&lt;/p&gt;
&lt;p&gt;And it’s not just users vs. publishers and advertisers. There are
many other influential groups on the web making the balance of interests
difficult. Some are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;You&lt;/em&gt;. Including here for completeness. You want to visit
websites and be presented with accurate reproductions of what the
publishers intended … kind of. You don’t want to be bothered by stuff
that you don’t want, like advertisements. Also you want to be able to
consume content freely and without boundaries. You want a free and open
web.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Publishers&lt;/em&gt; who make content on the web and give you a
reason to visit it. There are many not-for-profit content that doesn’t
have any commercial interests, but for those that do, it is important
that they are able to make money publishing stuff. They also have lots
of shared interests with users such as being able to publish what they
want and to be able to reach their intended audiences. In addition
sometimes they want to be able to publish things without identifying
themselves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Advertisers&lt;/em&gt; who compete for your attention and make
money by influencing your behavior. One of the ways in which they
compete for your attention is by “renting” space alongside publishers’
content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Search Engines&lt;/em&gt; could be considered a kind of a publisher
but they are special enough to get their own category. Search engines
–at this point, mostly Google– act as the guides on the internet helping
users find the content that they want. For this to work, search engines
rely on the internet being open and free. Otherwise it would not be
possible to take users to where they want to go. Since search engines
are one of, if not, the primary tools users need on the internet they
are always integrated deep into the UA.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Copyright owners and content rights holders&lt;/em&gt; who are
worried that people on the internet might steal their content. So web
browsers have to incorporate &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_rights_management&quot;&gt;Digital
Rights Management&lt;/a&gt; components into the UA to limit what users can do
with protected content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Businesses&lt;/em&gt; who want to make sure that you continue to
trust the internet as a safe place to buy and sell stuff. So web
browsers sometimes have to incorporate security measures (which actually
help users a lot too) and easy to use payment methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Politicians&lt;/em&gt;. Yes those people. As much as we would like
to treat the internet as some sort of ungovernable utopia, it isn’t.
There are many laws and regulations that are different across political
boundaries. So sometimes UAs need to report &lt;em&gt;where&lt;/em&gt; you are
physically so that your activity can be kept within legal bounds.
Politicians and businesses often also want to control what you are and
aren’t able to access on the internet. However, they take those issues
up with publishers and internet service providers. Additional shady
things politicians want include finding out the real identities of
people who have said things they don’t like.&lt;/p&gt;
&lt;p&gt;Shady stuff aside, politicians are also very useful. In fact as we
will see below, legislation is pretty much the only way in which users
can influence the big UA makers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Internet Service Providers&lt;/em&gt; (or ISPs) make money by
making it possible for you to access the internet. You give them some
money, and they give you internet access. Seems simple, but there are
lots of shady things that ISPs want, like to charge you based on
&lt;em&gt;what&lt;/em&gt; you consume. See &lt;a href=&quot;https://en.wikipedia.org/wiki/Net_neutrality&quot;&gt;network
neutrality&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that is hardly a complete list, but I believe we covered some of
the biggest influences.&lt;/p&gt;
&lt;h3 id=&quot;but-how-do-we-know-how-the-ua-balances-conflicting-interests&quot;&gt;But
how do we know how the UA balances conflicting interests?&lt;/h3&gt;
&lt;p&gt;But how do we know that the UA isn’t completely complicit and isn’t
selling our furniture without our knowledge? Why would we believe the UA
is doing what it says it is doing? What does &lt;q&gt;too much about me&lt;/q&gt;
even mean?&lt;/p&gt;
&lt;div class=&quot;sidenote-host-2&quot;&gt;
&lt;p&gt;Well &lt;q&gt;back in my day&lt;/q&gt; one would crack open the UA and take a
look inside. Usually, things are simple enough that you can convince
yourself, or someone you trust can convince you, that it is in fact
doing what it says it is doing.&lt;/p&gt;
&lt;p&gt;But modern UAs are so complex that such human inspection is
impractical at best. Not only would you have to inspect millions of
lines of code, you would have to inspect every new change as it comes
in. Even then, there are parts of most commercial browsers that are
closed source (i.e. they won’t let you look inside).&lt;/p&gt;
&lt;p&gt;So most of us have to trust the judgment and moral compass of the
thousands of specialists poring over the underlying logic.&lt;/p&gt;
&lt;/div&gt;
&lt;aside class=&quot;sidenote-2&quot;&gt;
&lt;h3 id=&quot;are-uas-really-unverifiable&quot;&gt;Are UAs really unverifiable?&lt;/h3&gt;
&lt;p&gt;Okay, so this might be a bit too harsh. Aren’t the biggest names in
the browser game open source? Aren’t they all, like, based on Chromium?
Why can’t we just read the source code and figure out whether it is
doing anything odd?&lt;/p&gt;
&lt;p&gt;The reality is that people &lt;em&gt;have&lt;/em&gt; and are actively watching
open source browser projects with eagle eyes. There are even more people
making sure any new standards on the web are good and are in the
interest of users. Unfortunately, even if we can verify the open source
parts of the browser, that’s not the end of the story. See, when you
visit a web site, there could be data being sent to hundreds of
websites. Even if the browser tells you each and every one of those web
sites, it would not be practical for anyone to manually vet and
understand what is going on. Even beyond that, not all the functional
bits of a browser are open-source. In fact, perhaps the most
questionable parts of a browser –like AI integration, media rights
management, how it works with various hardware devices– are closed
source for many reasons.&lt;/p&gt;
&lt;p&gt;So it all boils down to whether it really matters if your security
depends on you performing something infeasible for all practical
purposes; kinda like being forced to read each and every privacy policy
and binding contract you have to click through.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&quot;it-matters-who-owns-the-user-agent.&quot;&gt;It matters who owns the
User-Agent.&lt;/h3&gt;
&lt;p&gt;We’ve established that modern UAs…:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;… are super complicated.&lt;/li&gt;
&lt;li&gt;… have to blance conflicting interests of the user, publishers,
advertisers, search engines, other businesses, copyright owners,
politicians, internet service providers, and others.&lt;/li&gt;
&lt;li&gt;… are not designed 100% in your favor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite vigilant oversight users still have to trust, without
verification, how a UA works.&lt;/p&gt;
&lt;p&gt;If you don’t trust one, you can always pick another. But you can’t
avoid taking &lt;em&gt;someone’s&lt;/em&gt; word that the UA is safe. Because of how
little control we have as users over browsers, the only real way in
which users can influence UAs is via legislation that holds UA owners
accountable for their design decisions.&lt;/p&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-w3c:webuseragents&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Yasskin, J., &amp;amp; Capadisli, S. (2026). &lt;em&gt;Web user agents&lt;/em&gt;. &lt;a href=&quot;https://www.w3.org/TR/web-user-agents/#audience&quot; class=&quot;uri&quot;&gt;https://www.w3.org/TR/web-user-agents/#audience&lt;/a&gt;. &lt;a href=&quot;https://www.w3.org/TR/web-user-agents/#audience&quot;&gt;https://www.w3.org/TR/web-user-agents/#audience&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;I’m using the term “device” loosely here because the
user agent often consists of an entire stack of hardware and software.
In literature, you’ll find the terms “device,” “machine,” and “system”
used interchangeably, depending on the context.&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;The term &lt;em&gt;web-user-agent&lt;/em&gt; doesn’t appear much in
technical literature with a rare exception. E.g. &lt;span class=&quot;citation&quot; data-cites=&quot;w3c:webuseragents&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#ref-w3c:webuseragents&quot; role=&quot;doc-biblioref&quot;&gt;Yasskin &amp;amp; Capadisli, 2026&lt;/a&gt;)&lt;/span&gt;&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;What’s the difference between a program and a platform?
The latter is something upon which other programs can run. While the
original world-wide-web was document-oriented (i.e. the “internet”
consisted of documents that linked to other documents), as technology
progressed, the web browser became more and more capable of presenting
complex behaviors. At the start they were just aesthetic – like blinking
text or changing how a link looks like when you hover the mouse cursor
over it. But over time, they have gained capabilities that rival native
applications. Look at &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API&quot;&gt;all the APIs&lt;/a&gt;
that are available &lt;em&gt;inside&lt;/em&gt; a browser.&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn4&quot;&gt;&lt;p&gt;I worked on Google Chrome for over a decade on the
networking stack, and briefly on the renderer. The amount of
documentation that it takes to describe how a web browser works is in
the order of tens of thousads of pages.&lt;/p&gt;
&lt;p&gt;Even then it is an understatement. The web works despite countless
quirks and misbehaviors. That’s because modern browsers handle those
quirks “correctly” to give the impression that everything is fine. These
quirks and how to handle them aren’t necessarily written down anywhere.
Browsers can’t just refuse to talk to large portions of the internet or
refuse to render millions of older web pages just because the code
wouldn’t look good.&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref4&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn5&quot;&gt;&lt;p&gt;Pun intended.&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref5&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn6&quot;&gt;&lt;p&gt;This ad-supported model of the open web sounds terrible;
and in some ways it is. There are some alternatives that have been
proposed over the years, but none have been successful as ads. Many
approaches involve internet users making payments of some kind to
publishers. Unfortunately, all such models have the downside that those
who are impoverished will get kicked out of our global information
village. So for now, this is the best we can do.&lt;/p&gt;
&lt;p&gt;AI will probably do in a few years what privacy advocates have tried
to do for decades; which is to kill the ad-supported web. As yet it’s
unclear what will replace it, and whom this replacement leaves behind.&lt;a href=&quot;https://xn--izc.com/posts/user-agents/#fnref6&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>What&#39;s your cog ratio?</title>
      <link href="https://xn--izc.com/posts/cog-ratio/" />
      <updated>2025-12-16T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/cog-ratio/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;As far as product development is concerned, the only thing that
matters is the change we make in the user experience. We want our users
to be happier because our product exists or, at the very least, less
sad.&lt;/p&gt;
&lt;p&gt;So when we build things we expect that our work will result in a
positive change for our users.&lt;/p&gt;
&lt;p&gt;However not everyone is in the business of making direct changes to
products. In fact not even developers&lt;a href=&quot;https://xn--izc.com/posts/cog-ratio/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; spend every minute
building things. Instead most of the work on a mature product has to do
with planning, monitoring, testing, discussing, deliberating, and doing
all manner of tasks that have no direct bearing on the material&lt;a href=&quot;https://xn--izc.com/posts/cog-ratio/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; composition of the product.&lt;/p&gt;
&lt;p&gt;Roles like program managers and product managers are one more degree
removed from the engineered product. On top of that managers, HR,
finance, and all the supporting roles are even further removed from the
user experience.&lt;/p&gt;
&lt;p&gt;Support infrastructure like build systems, testing infrastructure,
and monitoring infrastructure help people build, monitor, and improve
the product. However, the people working on the infrastracture are even
further removed from the form and function of the final product.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/cog-ratio/arthur-granson-machine-with-concrete.jpg&quot; class=&quot;noinvert&quot; alt=&quot;Arthur Ganson - Machine with Concrete. The gear reductions mean the final gear will make one revolution in over 2 trillion years. The machine runs uninterrupted even though the final gear is embedded in concrete, and cannot rotate. CC BY-SA 3.0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Arthur Ganson - &lt;a href=&quot;https://en.wikipedia.org/wiki/Arthur_Ganson#/media/File:Arthur_Ganson-Machine_with_Concrete-AEC-002.jpg&quot;&gt;Machine
with Concrete&lt;/a&gt;. The gear reductions mean the final gear will make one
revolution in over 2 trillion years. The machine runs uninterrupted even
though the final gear is embedded in concrete, and cannot rotate. CC
BY-SA 3.0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In common parlance, the term &lt;em&gt;cog ratio&lt;/em&gt; refers to the ratio
of the number of teeth of one cog to the number of teeth of another cog.
It translates to the number of turns we expect from the driven cog for
each turn of the driving cog.&lt;/p&gt;
&lt;p&gt;It’s cliche to think of ourselves as cogs in a large machine. But if
we do, it seems natural to wonder what our cog ratio is with respect to
the final products we ship our users.&lt;/p&gt;
&lt;p&gt;This is specially true when the products we work on are not end user
products, but are either infrastructure or support products that help
people who help people who … build the product. What would the effect be
if this product or service you are working on didn’t exist? By how much
do you think your work will improve the lives of our users?&lt;/p&gt;
&lt;p&gt;Does the product improve no matter how fast you turn?&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Contrary to common belief, developers in larger outfits
spend most of their time communicating with each other rather than
building things. See &lt;a href=&quot;https://komoroske.com/slime-mold/&quot;&gt;Coordination Headwinds&lt;/a&gt; by
Alex Komoroske.&lt;a href=&quot;https://xn--izc.com/posts/cog-ratio/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;We are using the term “material” loosely here, since
software products aren’t technically material. It refers to the bits and
bytes that comprise the product.&lt;a href=&quot;https://xn--izc.com/posts/cog-ratio/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Optimal line-length for publishing on the web</title>
      <link href="https://xn--izc.com/posts/optimal-line-length/" />
      <updated>2025-10-05T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/optimal-line-length/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Fonts should be pretty, and text layout should be easy to read as
possible. When publishing on paper, publishers can control the physical
format for the presentation. We can assume, for the most part, how
someone might hold and read a book or a newspaper. Based on that we can
predict how various layouts, typefaces, and letter sizes will affect the
readability and aesthetics.&lt;/p&gt;
&lt;p&gt;Publishing on the web is a bit more complicated. How exactly a web
page will be perceived is difficult to predict. Content publishers adapt
with responsive designs and share the responsibility for presentation
with browser makers and device makers.&lt;/p&gt;
&lt;div class=&quot;two-columns&quot;&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/nytimes-19150111.jpg&quot; title=&quot;An old newspaper, discolored and fuzzy. There are 8 columns of text on the front page along with some ads and articles that occasionally cross column boundaries.&quot; class=&quot;noinvert flush-right&quot; alt=&quot;New York Times print edition. 1915. (Image source: The Internet Archive)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;New York Times print edition. 1915.
(Image source: The Internet Archive)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Folks old enough to remember old timey newspapers would recall how
narrow their text columns were. Before digital layouts, newspapers were
published using &lt;em&gt;hot metal&lt;/em&gt; methods called &lt;em&gt;linotype&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linotype newspapers had narrow columns for practical
reasons&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A metal line of type (“&lt;em&gt;line-o-type&lt;/em&gt;” ⇝ &lt;em&gt;linotype&lt;/em&gt;)
also called a &lt;em&gt;slug&lt;/em&gt; becomes difficult to work with if it is too
long. In particular, the machines assembled text line-by-line. This
process requires that all the lines are roughly of equal width. A small
line width –2 inches in this case– was apparently the right
trade-off.&lt;/p&gt;
&lt;p&gt;There were additional reasons for the 8 column layouts of yore that
were not just ease of arranging type. For example, the many small
columns allowed for more flexibility for laying out ads.&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/linotype-slug.png&quot; class=&quot;noinvert&quot; alt=&quot;A linotype “slug” is a block of lead that has letter shaped extrusions on one side. (Image source: Wikimedia CC by-SA)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A linotype “slug” is a block of lead that
has letter shaped extrusions on one side. (Image source: &lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Linotype_Gusszeile_-_Type_Slug.jpg&quot;&gt;Wikimedia&lt;/a&gt;
CC by-SA)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;More relevant for us is that a narrow column makes it easier to find
the start of the next line after reading one. Larger spacing between
lines helps; double-spacing isn’t just a trick to push the page
count.&lt;/p&gt;
&lt;p&gt;Around 2008, New York Times changed the print layout to a wider 6
column layout. The new column size accommodated 40–45 characters. Since
fiddling with linotype slugs is no longer a concern, they were able to
focus more on readability.&lt;/p&gt;
&lt;p&gt;Newspapers – or print in general – is different from reading on the
web in terms of distance from the eye to the text. Different reading
distances demand different amounts of precision to follow a line of
text.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/line-tracking.png&quot; alt=&quot;An eyeball moves from the end of one line to the next and then moves to the beginning of the next line.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;An eyeball moves from the end of one line
to the next and then moves to the beginning of the next
line.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So the goal here is to figure out a width that is short enough that
the reader can find the next line comfortably, and long enough to not
require excessive effort to read each line. Too long and the reader will
break their rhythm with excessive time spent finding the start of the
next line. Too short and the reader will break their rhythm with
excessive time spent in saccadian movement.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/reading-effort-system.png&quot; alt=&quot;System diagram showing the optimization problem of reading comfort. An increase in line length leads to a decrease in saccadian effort, but an increase in line tracking effort. An increase in line spacing leads to an increase in sccadian effort, but a decrease in line tracking effort. An increase in distance to text results in a decrease in saccadian effort, but an increase in line tracking effort.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;System diagram showing the optimization
problem of reading comfort. An increase in line length leads to a
&lt;em&gt;decrease&lt;/em&gt; in saccadian effort, but an &lt;em&gt;increase&lt;/em&gt; in line
tracking effort. An increase in line spacing leads to an
&lt;em&gt;increase&lt;/em&gt; in sccadian effort, but a &lt;em&gt;decrease&lt;/em&gt; in line
tracking effort. An increase in distance to text results in a
&lt;em&gt;decrease&lt;/em&gt; in saccadian effort, but an &lt;em&gt;increase&lt;/em&gt; in line
tracking effort.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;What’s the optimal line length for the web then?&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et al.
(&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;
studied this very question. Their study looked at three different
layouts presented on what would be considered a regular desktop
screen.&lt;/p&gt;
&lt;p&gt;Examples of the three layouts from the &lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;
paper are presented below and are illustrative of what the test subjects
saw.&lt;/p&gt;
&lt;div class=&quot;horizontal&quot;&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/bernard-2003-full-length-example.png&quot; alt=&quot;Example of a full length layout. Image source Bernard et al. (2003)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Example of a full length layout. Image
source &lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et
al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/bernard-2003-medium-length-example.png&quot; alt=&quot;Example of a medium length layout. Image source Bernard et al. (2003)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Example of a medium length layout. Image
source &lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et
al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/optimal-line-length/bernard-2003-narrow-length-example.png&quot; alt=&quot;Example of a narrow length layout. Image source Bernard et al. (2003)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Example of a narrow length layout. Image
source &lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et
al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;From the paper (emphasis mine):&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;strong&gt;No differences were found for either reading time or
efficiency for either adults or children.&lt;/strong&gt; However,
&lt;strong&gt;adults preferred shorter line lengths&lt;/strong&gt; to full-screen
line lengths. In examining perception of reading efficiency, the results
were mixed. For adults, the full text lengths were perceived as
providing the optimal amount of scrolling in comparison to the two other
narrower line length conditions. The narrowest line length condition was
perceived as promoting the highest amount of reader concentration, while
the medium line-length condition was considered to be the most optimally
presented length for reading.&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;– &lt;span class=&quot;citation&quot; data-cites=&quot;bernard2003effects&quot;&gt;Bernard et
al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-bernard2003effects&quot; role=&quot;doc-biblioref&quot;&gt;2003&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;span class=&quot;citation&quot; data-cites=&quot;beymerRussellOrton&quot;&gt;Beymer et al.
(&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-beymerRussellOrton&quot; role=&quot;doc-biblioref&quot;&gt;2005&lt;/a&gt;)&lt;/span&gt;
performed an eye-tracking study along these same lines.&lt;/p&gt;
&lt;p&gt;From the paper:&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;Comparing the wide and narrow formatting conditions, our analysis
shows that for narrow formatting, subjects (a) read slightly faster, (b)
have fewer regressions, (c) retain more information in a post-test of
the material, but (d) tend to abandon the ends of longer paragraphs.&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;– &lt;span class=&quot;citation&quot; data-cites=&quot;beymerRussellOrton&quot;&gt;Beymer et
al. (&lt;a href=&quot;https://xn--izc.com/posts/optimal-line-length/#ref-beymerRussellOrton&quot; role=&quot;doc-biblioref&quot;&gt;2005&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In other words, there’s a &lt;em&gt;slight&lt;/em&gt; preference for narrower
columns, but there’s no consensus on whether there’s a significant
improvement in reading speed. Some evidence exists to suggest that
comprehension is slightly better with narrower columns.&lt;/p&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-bernard2003effects&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Bernard, M. L., Fernandez, M., Hull, S., &amp;amp; Chaparro, B. S. (2003).
The effects of line length on children and adults’ perceived and actual
online reading performance. &lt;em&gt;Proceedings of the Human Factors and
Ergonomics Society Annual Meeting&lt;/em&gt;, &lt;em&gt;47&lt;/em&gt;, 1375–1379.
&lt;/div&gt;
&lt;div id=&quot;ref-beymerRussellOrton&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Beymer, D., Russell, D. M., &amp;amp; Orton, P. Z. (2005). Wide vs. Narrow
paragraphs: An eye tracking analysis. In M. F. Costabile &amp;amp; F.
Paternò (Eds.), &lt;em&gt;Human-computer interaction - INTERACT 2005&lt;/em&gt; (pp.
741–752). Springer Berlin Heidelberg.
&lt;/div&gt;
&lt;/div&gt;

      </content>
    </entry>
    <entry>
      <title>An Intuition on Shannon Entropy</title>
      <link href="https://xn--izc.com/posts/an-intuition-on-entropy/" />
      <updated>2025-09-27T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/an-intuition-on-entropy/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;preface&quot;&gt;
&lt;p&gt;This post skips over an in-depth explanation of &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropy_(information_theory)&quot;&gt;Shannon
entropy&lt;/a&gt; and only addresses the intuition surrounding it and how it
can be misleading. Googling for “information theory” should come up with
plenty of options for a more thorough treatment of information
theory.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In &lt;a href=&quot;https://en.wikipedia.org/wiki/Information_theory&quot;&gt;information
theory&lt;/a&gt;, entropy is a way to measure &lt;em&gt;“uncertainty”&lt;/em&gt; or
alternatively a measure of &lt;em&gt;“information”&lt;/em&gt;. The field of
information theory itself was first formalized by &lt;a href=&quot;https://en.wikipedia.org/wiki/Claude_Shannon&quot;&gt;Claude Shannon&lt;/a&gt;
who’s name comes up often in the literature.&lt;/p&gt;
&lt;p&gt;Conceptually &lt;em&gt;information&lt;/em&gt; and &lt;em&gt;uncertainty&lt;/em&gt; are
opposing forces. More of one and you have less of the other.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/an-intuition-on-entropy/scale.jpg&quot; title=&quot;An allegorical pencil drawing of an ornate scale. The left pan represents &amp;#39;Information&amp;#39; with a neat pile of books and scrolls. The right pan represents &amp;#39;Uncertainty&amp;#39; with a chaotic vortex of dissolving papers, gears, and symbols. The scale is in perfect equilibrium, illustrating the conceptual balance between order and disorder.&quot; alt=&quot;The balance between Information and Uncertainty. Not “uncetrinity”; I don’t know what Gemini was thinking there. (Generated with Gemini.)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The balance between Information and
Uncertainty. Not “uncetrinity”; I don’t know what Gemini was thinking
there. (Generated with Gemini.)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Lack of information leads to uncertainty. In the absence of any
information we are in total uncertainty.&lt;/p&gt;
&lt;p&gt;In practice in any given situation where we are concerned with
information begins with a well defined foundation which lays out a set
of possible outcomes. Each piece of information we receive should narrow
down the set of possible outcomes until we reach an unambiguously
certain outcome.&lt;/p&gt;
&lt;p&gt;If we only have one possible outcome, then we are certain of that
outcome. The measure of uncertainty could be thought of as a way of
measuring how far we have to go to get there.&lt;/p&gt;
&lt;h3 id=&quot;shannon-entropy-is-a-measure-of-uncertainty&quot;&gt;Shannon entropy is
a measure of uncertainty&lt;/h3&gt;
&lt;p&gt;A good example of this is the classic game &lt;em&gt;“Guess who”&lt;/em&gt;,
where you have to guess a person from a set of pictures based on a few
pieces of information.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/an-intuition-on-entropy/guess-who.jpg&quot; class=&quot;noinvert&quot; alt=&quot;The original cast of characters of the game “Guess Who”&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The original cast of characters of the
game “Guess Who”&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We want to pinpoint a person of interest; which in this case
translates to narrowing down the list of possibilities to 1. Each person
has an equal probability of being the person of interest. Therefore at
the beginning our uncertainty is 1 in 24 — or equivalently &lt;span class=&quot;math inline&quot;&gt;&#92;frac{1}{24}&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Let’s look at two possible pieces of information:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;wears glasses – matches 5 persons&lt;/li&gt;
&lt;li&gt;presents as a man – matches 18 persons&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We started with 24 possibilities. Once we know that the person of
interest is wearing glasses, we can narrow down the field to 5. On the
other hand, knowing that the person presents as a man only narrows down
the field to 18. The first piece of information is &lt;em&gt;clearly more
valuable&lt;/em&gt; than the second. By &lt;em&gt;“valuable”&lt;/em&gt; we mean
&lt;em&gt;“reduces uncertainty”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Entropy is a way to quantify –or measure– this valuableness.&lt;/p&gt;
&lt;h3 id=&quot;choices-of-measure-for-a-single-outcome&quot;&gt;Choices of measure for
a single outcome&lt;/h3&gt;
&lt;p&gt;For the sake of discussion, let’s say the probability of a single
outcome (call it &lt;span class=&quot;math inline&quot;&gt;A&lt;/span&gt;) is &lt;span class=&quot;math inline&quot;&gt;&#92;Pr(A)&lt;/span&gt;. And the measure of information
learned from knowing this outcome is &lt;span class=&quot;math inline&quot;&gt;M(A)&lt;/span&gt;, where &lt;span class=&quot;math inline&quot;&gt;M&lt;/span&gt; is some function which we will figure out
here.&lt;/p&gt;
&lt;h4 id=&quot;adding-independent-pieces-of-information-should-correspond-to-adding-entropy&quot;&gt;Adding
independent pieces of information should correspond to adding
entropy&lt;/h4&gt;
&lt;p&gt;Channeling some high school math, we know that if the probability of
event &lt;span class=&quot;math inline&quot;&gt;A&lt;/span&gt; happenning is &lt;span class=&quot;math inline&quot;&gt;p&lt;/span&gt;, and the probability of event &lt;span class=&quot;math inline&quot;&gt;B&lt;/span&gt; happening is &lt;span class=&quot;math inline&quot;&gt;q&lt;/span&gt;, and if these two events are
&lt;em&gt;independent&lt;/em&gt;, then the probability of both happening is going to
be &lt;span class=&quot;math inline&quot;&gt;pq&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;For example, the event &lt;em&gt;person is in the first row&lt;/em&gt; (&lt;span class=&quot;math inline&quot;&gt;A&lt;/span&gt;) has a probability of &lt;span class=&quot;math inline&quot;&gt;p = &#92;frac{1}{3}&lt;/span&gt;, while the event &lt;em&gt;person
is in the third column&lt;/em&gt; (&lt;span class=&quot;math inline&quot;&gt;B&lt;/span&gt;) has a
probability of &lt;span class=&quot;math inline&quot;&gt;q = &#92;frac{1}{8}&lt;/span&gt;.
Meanwhile, both of these happenning at the same time (&lt;span class=&quot;math inline&quot;&gt;A &#92;wedge B&lt;/span&gt; ; where you can read the &lt;span class=&quot;math inline&quot;&gt;&#92;wedge&lt;/span&gt; as &lt;em&gt;and&lt;/em&gt;) has a probability of
&lt;span class=&quot;math inline&quot;&gt;pq = &#92;frac{1}{3} &#92;cdot &#92;frac{1}{8} =
&#92;frac{1}{24}&lt;/span&gt;. I.e.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
A &#92;text{ and } B &#92;text{ are independent events} &#92;implies &#92;Pr(A &#92;wedge B)
= &#92;Pr(A) &#92;cdot P(B) = pq
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A good measure should be intuitive. Which is to say, it should behave
in ways that we expect. So for example, if we were to take two
&lt;em&gt;independent&lt;/em&gt; signals, adding them should yield a measure equal
to the sum of each measured separately.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
&#92;begin{equation}
A &#92;text{ and } B &#92;text{ are independent events } &#92;implies M(A &#92;wedge B)
= M(A) + M(B)
&#92;end{equation}
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The simplest way to convert a multiplication like &lt;span class=&quot;math inline&quot;&gt;pq&lt;/span&gt; to a sum is to … drumroll … take the
&lt;em&gt;logarithm&lt;/em&gt;. So we could start with &lt;span class=&quot;math inline&quot;&gt;M(p)&lt;/span&gt; being something like &lt;span class=&quot;math inline&quot;&gt;&#92;log(p)&lt;/span&gt;.&lt;/p&gt;
&lt;h4 id=&quot;more-uncertainty-should-correspond-to-a-larger-entropy&quot;&gt;More
uncertainty should correspond to a larger entropy&lt;/h4&gt;
&lt;p&gt;To further intuit, an outcome with a lower probability is more
surprising and hence strictly more informative than an outcome with a
higher probability, we need:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
&#92;begin{equation}
&#92;Pr(A) &#92;lt &#92;Pr(B) &#92;implies M(A) &#92;gt M(B)
&#92;end{equation}
&lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;no-uncertainty-should-correspond-to-zero-entropy&quot;&gt;No uncertainty
should correspond to zero entropy&lt;/h4&gt;
&lt;p&gt;In other words,&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
&#92;begin{equation}
&#92;Pr(A) = 1 &#92;implies M(A) = 0
&#92;end{equation}
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;because the outcome &lt;span class=&quot;math inline&quot;&gt;A&lt;/span&gt; is going to
happen with certainty.&lt;/p&gt;
&lt;h4 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;/h4&gt;
&lt;p&gt;The simplest way to make entropy larger for outcomes with lower
probability is to negate the logarithm. Doing so has the additional
desirable effect that probabilities –which are in the range &lt;span class=&quot;math inline&quot;&gt;[0,1]&lt;/span&gt;– will yield positive values.&lt;/p&gt;
&lt;p&gt;So finally, we have the measure:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
M(A) = - &#92;log&#92;left( &#92;Pr(A) &#92;right)
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Since Claude Shannon was interested in measuring the information
content of digital signals at the time, it made sense to use a more
familiar base for the logarithm like &lt;span class=&quot;math inline&quot;&gt;2&lt;/span&gt;
instead of &lt;span class=&quot;math inline&quot;&gt;e&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So the final equation is:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
M &#92;left( p &#92;right) = - &#92;log_2&#92;left( p &#92;right)
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The choice of &lt;span class=&quot;math inline&quot;&gt;2&lt;/span&gt; as the base has
another nice feature that we can now interpret the information quantity
as a &lt;em&gt;number of bits&lt;/em&gt;. Because, for example, if we have 5 bits of
information where each of the 32 values is equally likely, then any
specific outcome has a probability of &lt;span class=&quot;math inline&quot;&gt;&#92;frac{1}{2^5}&lt;/span&gt; of occurring.&lt;/p&gt;
&lt;p&gt;So knowing the outcome gets us &lt;span class=&quot;math inline&quot;&gt;M(&#92;frac{1}{2^5})&lt;/span&gt; amount of information; which
happens to be &lt;span class=&quot;math inline&quot;&gt;5&lt;/span&gt; — the number of bits we
started with.&lt;/p&gt;
&lt;p&gt;This measure of information for a single event is called the
&lt;strong&gt;pointwise entropy&lt;/strong&gt;, or &lt;strong&gt;self
information&lt;/strong&gt;. &lt;em&gt;“Pointwise”&lt;/em&gt; because it is measuring a
single outcome in the probability space.&lt;/p&gt;
&lt;h3 id=&quot;choice-of-measure-for-a-probability-space&quot;&gt;Choice of measure for
a probability space&lt;/h3&gt;
&lt;p&gt;Now that we have a measure of the information content of a single
outcome, how do we measure the information content of a probability
space?&lt;/p&gt;
&lt;p&gt;For this, we take another simple formula we already know; which is
the &lt;em&gt;expectation&lt;/em&gt;. Hence we define the information content of a
probability space to be the &lt;em&gt;expected&lt;/em&gt; pointwise entropy.&lt;/p&gt;
&lt;p&gt;This entropy of a probability space is often denoted &lt;span class=&quot;math inline&quot;&gt;H(P)&lt;/span&gt; where &lt;span class=&quot;math inline&quot;&gt;P&lt;/span&gt;
is the probability space (defined formally below). For simplicity we can
think of &lt;span class=&quot;math inline&quot;&gt;P&lt;/span&gt; as being a function of some
outcome to the probability of that outcome.&lt;/p&gt;
&lt;p&gt;The expected pointwise entropy is therefore:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
&#92;begin{equation*}
&#92;begin{split}
H(P) &amp;amp;= &#92;sum_{&#92;omega &#92;in &#92;Omega} P(&#92;omega) &#92;cdot M(&#92;omega) &#92;&#92;
     &amp;amp;= - &#92;sum_{&#92;omega &#92;in &#92;Omega} P(&#92;omega) &#92;cdot &#92;log_2&#92;left(
P(&#92;omega) &#92;right)
&#92;end{split}
&#92;end{equation*}
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Where &lt;span class=&quot;math inline&quot;&gt;&#92;Omega&lt;/span&gt; is the set of all
possible outcomes.&lt;/p&gt;
&lt;h2 id=&quot;formalities&quot;&gt;Formalities&lt;/h2&gt;
&lt;p&gt;A common critique is that Shannon entropy can be misleading. Let’s
see why.&lt;/p&gt;
&lt;p&gt;Let’s start with a &lt;strong&gt;probability space&lt;/strong&gt;. It consists
of:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;A set of possible outcomes. Usually designated as &lt;span class=&quot;math inline&quot;&gt;&#92;Omega&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;For example, the set of possible &lt;em&gt;person-of-interest&lt;/em&gt; consists
of the 24 individuals who are pictured above.&lt;/p&gt;
&lt;p&gt;Note that here we are dealing with a &lt;em&gt;discrete&lt;/em&gt; probability
space in that we have a countable set of possible outcomes. This isn’t
always the case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A set of subsets of possible outcomes. Usually designated as
&lt;span class=&quot;math inline&quot;&gt;&#92;mathcal{F}&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In our example, it could be &lt;em&gt;people with moustaches&lt;/em&gt;,
&lt;em&gt;people wearing hats&lt;/em&gt;, &lt;em&gt;people with glasses&lt;/em&gt;, etc. The set
doesn’t need to have any semantic meaning. So any group of people from
the 24 possible people is a valid subset.&lt;/p&gt;
&lt;p&gt;Typically there would be one element in &lt;span class=&quot;math inline&quot;&gt;&#92;mathcal{F}&lt;/span&gt; which contains all the possible
outcomes. I.e. we say &lt;span class=&quot;math inline&quot;&gt;&#92;Omega &#92;in
&#92;mathcal{F}&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A probability function. Usually designated as &lt;span class=&quot;math inline&quot;&gt;P&lt;/span&gt;, that when applied to an element in &lt;span class=&quot;math inline&quot;&gt;&#92;mathcal{F}&lt;/span&gt; yields the probability of that
set of outcomes occurring.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;P(&#92;text{wears glasses}) =
&#92;frac{5}{24}&lt;/span&gt; &lt;span class=&quot;math display&quot;&gt;P(&#92;text{presents as a
man}) = &#92;frac{18}{24}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also, when applied to &lt;span class=&quot;math inline&quot;&gt;&#92;Omega&lt;/span&gt;
(i.e. the set of all possible outcomes), it yields &lt;span class=&quot;math inline&quot;&gt;1&lt;/span&gt; as one would expect since otherwise it
would not be the set of all possible outcomes. I.e.:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;P(&#92;Omega) = 1&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Let&lt;/strong&gt; &lt;span class=&quot;math inline&quot;&gt;(&#92;Omega, &#92;mathcal{F},
P)&lt;/span&gt; be a probability space.&lt;/p&gt;
&lt;p&gt;So, &lt;span class=&quot;math inline&quot;&gt;&#92;mathcal{F}&lt;/span&gt; is the set of all
possible subsets of &lt;span class=&quot;math inline&quot;&gt;&#92;Omega&lt;/span&gt;, which is
also written as &lt;span class=&quot;math inline&quot;&gt;2^{&#92;Omega}&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;mathcal{F} = 2^{&#92;Omega}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;… and …&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math inline&quot;&gt;P&lt;/span&gt; is a function that maps from &lt;span class=&quot;math inline&quot;&gt;&#92;mathcal{F}&lt;/span&gt; to the real numbers in the range
0 thru 1 inclusive.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;P : &#92;mathcal{F} &#92;mapsto [0,1]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Shannon entropy of the probability function &lt;span class=&quot;math inline&quot;&gt;P&lt;/span&gt; is given by:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;
H(P) = - &#92;sum_{&#92;omega &#92;in &#92;Omega} P(&#92;omega) &#92;cdot &#92;log_2&#92;left( P(&#92;omega)
&#92;right)
&lt;/span&gt;&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Incentives</title>
      <link href="https://xn--izc.com/series/unsung-team-roles/incentives/" />
      <updated>2025-08-12T00:00:00Z</updated>
      <id>https://xn--izc.com/series/unsung-team-roles/incentives/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Teams can fail in many ways&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/incentives/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. But when they succeed,
the most critical roles are those that form the communication structures
within and across teams. Forming these structures require teammates to
have some level of autonomy. In turn this requires a team stucture that
allows the team the freedom of movement to reconfigure itself to serve
the teams’ goals.&lt;/p&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;h4 id=&quot;no-heros&quot;&gt;No Heros&lt;/h4&gt;
&lt;p&gt;Any organization whose success depends on their employees working
&lt;em&gt;against&lt;/em&gt; their own self interests will eventually fail.&lt;/p&gt;
&lt;p&gt;Unfortunately incentives are seldom constructed by those who
understand what organizational cross beams are necessary to keep the
&lt;em&gt;“official”&lt;/em&gt; organizational structure from collapsing.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://sre.google/resources/practices-and-processes/no-heroes/&quot;&gt;Why
Heroism Is Bad&lt;/a&gt; in the Google SRE site.&lt;/p&gt;
&lt;/aside&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;If the conditions are right, a healthy team will fill in the gaps by
rebalancing their responsibilities. Such a rebalancing will inevitably
lead to an uneven distribution of burden. With time the burden will
become increasingly visceral, which will lead to burnout, resentment,
and attrition. For an uneven burden to be sustained, that burden must be
commesurately rewarded.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Accurately measuring the contributions of each team member is a
hitherto unsolved problem. Managers are often left with gut instincts to
fall back on, which comes with a laundry list of shortcomings like bias
and favoritism. Those who come up with the right formula against all
odds are celebrated as &lt;em&gt;good managers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;People write books and give speeches about their favorite &lt;em&gt;good
manager&lt;/em&gt;. But often the actual skills involved aren’t articulated.
The list of skills isn’t long. Primarily these skills revolve around the
ability to understand what each person is &lt;em&gt;doing&lt;/em&gt;. Secondairly
they revolve around the ability to understand how those actions
&lt;em&gt;affect the rest of the team&lt;/em&gt;. Both require a manager to have
visibility into how the team interacts – either by direct observation or
by frequent and extensive communication with each team member.&lt;/p&gt;
&lt;p&gt;All of this still won’t do much if the team desn’t have psychological
safety. Without this, team members may not be willing to recognize and
reward their peers. Nor would they be liklely to disclose bad news in a
timely manner.&lt;/p&gt;
&lt;p&gt;Bad incentive structures lead to people ridigly performing just their
roles and letting things fail around them (&lt;em&gt;“it’s not my
job”&lt;/em&gt;).&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/incentives/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To summarize, good things happen when the incentives for a team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Never pit employees against each other. One person’s success cannot
be another’s downfall.&lt;/li&gt;
&lt;li&gt;Assume that the leadership hasn’t figured out exactly what needs to
be done. The team should be empowered to course-correct as they
learn.&lt;/li&gt;
&lt;li&gt;Reward those who pull the team together and help the team
communicate internally and externally.&lt;/li&gt;
&lt;/ul&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;I recommend &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Five_Dysfunctions_of_a_Team&quot;&gt;The
Five Dysfunctions of a Team&lt;/a&gt; for a nice run through of different ways
in which teams fail to function.&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/incentives/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;See &lt;a href=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/&quot;&gt;Intrinsic and Extrinsic
Motivation: An Anecdote&lt;/a&gt; for an example of what happens when people
try to force this process purely by creating extrinsic incentives and
assigned roles.&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/incentives/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Ode to Glue People</title>
      <link href="https://xn--izc.com/series/unsung-team-roles/glue-people/" />
      <updated>2025-08-12T00:00:00Z</updated>
      <id>https://xn--izc.com/series/unsung-team-roles/glue-people/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;The concept of glue work isn’t new. Team building, mentoring, running
meetings, and many other mundane tasks fall under this category of often
uncompensated work. How glue work establishes unofficial communication
structures within and across teams is, however, discussed less
often.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Not every manager is a great communicator; and that’s okay. This is
specially true in large tech companies where the people management
ladders are the natural next step for individual contributors who are
seeking career growth. When important information that affects people’s
careers isn’t communicated in a fair and timely manner, trust collapses
taking down the team with it.&lt;/p&gt;
&lt;p&gt;Bound by needs for confidentiality and mandatory reporting, managers
are often not the best people to confide in or trust. Meanwhile peers
with the right set of social skills become speakeasies: people with whom
others feel psychologically safe. The level of trust between a speakeasy
and other team members can be much higher than with managers.&lt;/p&gt;
&lt;p&gt;Consequently, these speakeasies become social hubs where both work
and non-work related information flow freely. Some might call it gossip.
But when the information is factual and timely, it can help teammates
made better decisions, at least for themselves if not for the company.
In times of turmoil – like the increasingly frequent
&lt;em&gt;“once-in-a-lifetime”&lt;/em&gt; recessions that keep happening in the US –
the glue people take on a dual role: as a pressure release valve for
individuals, and as a vehicle for breaking their sense of isolation.&lt;/p&gt;
&lt;p&gt;No surprise that such roles cannot be written down in a normal job
description. Also of no surprise that such roles aren’t recognized nor
compensated.&lt;/p&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;h4 id=&quot;losing-glue&quot;&gt;Losing Glue&lt;/h4&gt;
&lt;p&gt;I was tempted to write about this after the departure of a coworker.
The extent to which they were holding the team together was not apparent
until they left.&lt;/p&gt;
&lt;p&gt;Our team is spread out across many geographic regions, so pretty much
all of our interactions are online. Our team chats are more than just
sources of work information, they are also where most of the
socialization happens. So the tone and spirit of communication is
critical for engagement. Once the keeper of the spirit left, the chats
fell silent. And suddenly, it seemed, we became strangers.&lt;/p&gt;
&lt;/aside&gt;

      </content>
    </entry>
    <entry>
      <title>Soft Roles as Organizational Cross Beams</title>
      <link href="https://xn--izc.com/series/unsung-team-roles/crossbeams/" />
      <updated>2025-08-12T00:00:00Z</updated>
      <id>https://xn--izc.com/series/unsung-team-roles/crossbeams/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;Beyond the obvious team scoped function of soft roles, they also
perform important functions at the organizational level. Of these two
common types are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glue-people&lt;/strong&gt; who are necessary to tie teams
together, build cohesion, connect the dots between silos that are not
effectively communicating with each other, and establish an unofficial
foundation of trust that prevent teams from collapsing when the trust
between leadership and their underlings inevitably crumbles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immune Systems&lt;/strong&gt; are the people necessary to stop
the company from shooting themselves in their corporate feet. These are
the people who internally oppose measures that would cause widespread
collapse of user-trust, violate privacy policies, open up the
organization to litigation, irreversibly misuse customer data,
unnecessarily jeopardize the operational stability or security of
critical systems, or commit war crimes and human rights
violations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;h4 id=&quot;individual-failure-vs.-organizational-failures&quot;&gt;Individual
Failure vs. Organizational Failures&lt;/h4&gt;
&lt;p&gt;Unfortunately all the lessons we learn about human fallibility tend
to be forgotten the higher up the reporting chain we go. So even though
we expect and build in mechanisms to deal with individual failures, we
tend not to build mechanisms to deal with organizational failures. We
assume that organizations fail less often than individuals. The opposite
is true. Organizations are made up of people. The more people you have
the more likely it is that one of them will fail. The more people you
have the more likely it is that they will fail in a way that is
catastrophic to the organization.&lt;/p&gt;
&lt;/aside&gt;

      </content>
    </entry>
    <entry>
      <title>Emergence of Soft Roles</title>
      <link href="https://xn--izc.com/series/unsung-team-roles/emergence/" />
      <updated>2025-08-02T00:00:00Z</updated>
      <id>https://xn--izc.com/series/unsung-team-roles/emergence/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Google’s early success is partly attributed to the use of commodity
hardware that were expected to break occasionally. Rather than demanding
perfection from complex systems it is far more effective to expect and
design around imperfections&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/google-servers.jpg&quot; class=&quot;noinvert&quot; alt=&quot;By Erik Pitti from San Diego, CA, USA - Google’s First ServerUploaded by Mewtu, CC BY 2.0, Link&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;By
&lt;a rel=&quot;nofollow&quot; class=&quot;external text&quot; href=&quot;https://www.flickr.com/people/24205142@N00&quot;&gt;Erik
Pitti&lt;/a&gt; from San Diego, CA, USA -
&lt;a rel=&quot;nofollow&quot; class=&quot;external text&quot; href=&quot;https://www.flickr.com/photos/24205142@N00/2370851677/&quot;&gt;Google’s
First Server&lt;/a&gt;Uploaded by
&lt;a href=&quot;https://commons.wikimedia.org/w/index.php?title=User:Mewtu&amp;action=edit&amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User:Mewtu (page does not exist)&quot;&gt;Mewtu&lt;/a&gt;,
&lt;a href=&quot;https://creativecommons.org/licenses/by/2.0&quot; title=&quot;Creative Commons Attribution 2.0&quot;&gt;CC
BY 2.0&lt;/a&gt;,
&lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=8724999&quot;&gt;Link&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;Similarly when we design products, we design them for fallible users
who are prone to making occasional mistakes, and beholden to some number
of misconceptions.&lt;/p&gt;
&lt;/div&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;h4 id=&quot;misconceptions&quot;&gt;Misconceptions&lt;/h4&gt;
&lt;p&gt;The &lt;em&gt;misconceptions&lt;/em&gt; referred to here are misunderstandings of
how the product or process works. It could be situational
misunderstandings (e.g. confusion about how to accomplish an immediate
goal), or it could be a more persistent fundamental misunderstanding
about how something works (e.g. misunderstanding &lt;a href=&quot;https://support.mozilla.org/en-US/kb/common-myths-about-private-browsing&quot;&gt;how
private browsing works&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With real world problems, information flow is never perfect. Loss of
precision at each stage of discovery, analysis, prototyping, and
implementation leads to potential for misconceptions. See &lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/&quot;&gt;The Secret Life of Systems&lt;/a&gt; for
an illustration of how real world problems and the implementation of a
solution may not align.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;As we design products, so we must design our internal processes. We
once again assume that our teammates are fallible, prone to making
occasional mistakes, and operating under some number of misconceptions&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fallibility runs both ways up and down the org chart. Leaders operate
under vague, incomplete, and sometimes wildly inaccurate information&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;. Further complicating matters, it is
impossible to understand the capabilities and shortcomings of each
individual person or understand every nuance of what must constitute a
role.&lt;/p&gt;
&lt;p&gt;The result is that team roles are neither comprehensive nor precise.
In any given team structure people are expected to adapt to a broad
range of situations that are unpredictable, and frankly unknowable. Some
(most?) of those situations are directly due to other team members.&lt;/p&gt;
&lt;p&gt;As teams mature, the &lt;em&gt;actual&lt;/em&gt; role each person takes on will
gradually anneal around individual strengths and weaknesses forged by
need and cemented through consistency.&lt;/p&gt;
&lt;p&gt;So in reality, what is intended to be a neat and well circumscribed
role profile becomes irregular, illdefined, and dynamic.&lt;/p&gt;
&lt;div class=&quot;horizontal&quot;&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/hierarchical.svg&quot; title=&quot;A neat organization chart.&quot; class=&quot;noinvert&quot; alt=&quot;Expectation: Neatly circumscribed hierarchichal roles.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Expectation: Neatly circumscribed
hierarchichal roles.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/chaotic.svg&quot; title=&quot;A bunch of soft irregular shapes are squished together.&quot; class=&quot;noinvert&quot; alt=&quot;Reality: Smeared, lopsided, and chaotic roles.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Reality: Smeared, lopsided, and chaotic
roles.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;In short: Following the spirit of designing with imperfections, team
organization must always account for this fluidity of roles.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roles in a team will rarely be circumscribed by the corresponding
job description. People will always do work outside their scope.&lt;/li&gt;
&lt;li&gt;Roles will overlap in ways that will run counter to the intents of
the official role allocations. People will do other’s work
occasionally.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Roles will emerge that are not mentioned in anyone’s job
description.&lt;/em&gt; Sometimes called &lt;em&gt;soft&lt;/em&gt; roles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this series we will look at a few of these soft roles that emerge
often and look into the critical work that these roles perform.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;A former Googler, Avery Penwarr wrote an influential
document while they were at Google called &lt;em&gt;View from Above&lt;/em&gt; about
the perspective of executives. Fortunately he also wrote a public
version called &lt;a href=&quot;https://apenwarr.ca/log/?m=201909&quot;&gt;What do
executives do anyway?&lt;/a&gt;. The basic premise is that when it comes to
any big decision, the executive highest up the ladder is the least
informed about the pertinent details – but that’s okay because knowing
the details isn’t their job.&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;See &lt;a href=&quot;https://sre.google/sre-book/postmortem-culture/&quot;&gt;Postmortem
Culture: Learning from Failure&lt;/a&gt; for how anticipating mistakes lends
itself to a healthy culture where people proactively report and learn
from mistakes.&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;A former Googler, Avery Penwarr wrote an influential
document while they were at Google called &lt;em&gt;View from Above&lt;/em&gt; about
the perspective of executives. Fortunately he also wrote a public
version called &lt;a href=&quot;https://apenwarr.ca/log/?m=201909&quot;&gt;What do
executives do anyway?&lt;/a&gt;. The basic premise is that when it comes to
any big decision, the executive highest up the ladder is the least
informed about the pertinent details – but that’s okay because knowing
the details isn’t their job.&lt;a href=&quot;https://xn--izc.com/series/unsung-team-roles/emergence/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Draining Our Intellectual Catchment Areas</title>
      <link href="https://xn--izc.com/posts/catchment/" />
      <updated>2025-07-04T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/catchment/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It is July 4, 2025, and many major universities &lt;span class=&quot;citation&quot; data-cites=&quot;affectedUniversities&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-affectedUniversities&quot; role=&quot;doc-biblioref&quot;&gt;Alan Blinder,
n.d.&lt;/a&gt;)&lt;/span&gt; in the US are struggling to deal with threats and
funding cuts from the Trump administration.&lt;/p&gt;
&lt;p&gt;A major impact of funding cuts is the loss of enrollments of
promising students due to fewer programs. International students now
face an even more uncertain future where they may not be able to enroll
at all despite being accepted &lt;span class=&quot;citation&quot; data-cites=&quot;harvardGazette1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-harvardGazette1&quot; role=&quot;doc-biblioref&quot;&gt;Harvard Staff, 2025&lt;/a&gt;)&lt;/span&gt;, their student
status may be invalidated without notice &lt;span class=&quot;citation&quot; data-cites=&quot;bigImmigrationBlog1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-bigImmigrationBlog1&quot; role=&quot;doc-biblioref&quot;&gt;Big Immigration Law Blog, 2025&lt;/a&gt;)&lt;/span&gt;, they
are detained without recourse for exercising their rights &lt;span class=&quot;citation&quot; data-cites=&quot;time1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-time1&quot; role=&quot;doc-biblioref&quot;&gt;Charlotte Alter, 2024&lt;/a&gt;)&lt;/span&gt;, or they are
detained and denied entry to the US &lt;span class=&quot;citation&quot; data-cites=&quot;massLive1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-massLive1&quot; role=&quot;doc-biblioref&quot;&gt;Melissa Hanson, 2025&lt;/a&gt;)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In addition, funding cuts have resulted in universities having to
freeze academic programs or renege on accepted students &lt;span class=&quot;citation&quot; data-cites=&quot;bestColleges1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-bestColleges1&quot; role=&quot;doc-biblioref&quot;&gt;BestColleges Staff,
2025&lt;/a&gt;)&lt;/span&gt;, jeopardizing ongoing research programs. Also as a
side-effect, promising academics both in the US and abroad are looking
towards universities outside of the US &lt;span class=&quot;citation&quot; data-cites=&quot;npr1&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-npr1&quot; role=&quot;doc-biblioref&quot;&gt;Sequoia
Carrillo, 2025&lt;/a&gt;)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Let’s have a look at the role these academic institutions are playing
in the US’s industrial dominance, and the long-term effects of hampering
their progress.&lt;/p&gt;
&lt;section id=&quot;migrations-of-intellectual-capital&quot; class=&quot;preface&quot;&gt;
&lt;h3&gt;Migrations of Intellectual Capital&lt;/h3&gt;
&lt;p&gt;Throughout history a number of events have contributed to the present
distribution of intellectual capital. As of this writing (July of 2025)
the intellectual capital – especially when it comes to information
technology and biotech – is heavily concentrated in the east and west
coasts of the United States.&lt;/p&gt;
&lt;p&gt;Use the interactive timeline below to explore important events in the
migration of intellectual capital to and within the United States.&lt;/p&gt;
&lt;p&gt;For a more detailed treatement, see &lt;a href=&quot;https://xn--izc.com/posts/catchment/us-intellectual-capital-migration&quot;&gt;The Accumulation and
Migration of Intellectual Human Capital in the United States: A
Historical Analysis&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;div class=&quot;fullbleed&quot;&gt;
&lt;div class=&quot;fullbleed&quot;&gt;
  &lt;style&gt;
    /* Custom styles for the timeline */
    .timeline-container {
      position: relative;
      width: 100%;
      margin: 1rem 0 4rem;
    }
    .timeline-line {
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
      width: 100%;
      height: 4px;
      background-color: var(--border-color);
    }
    .timeline-events {
      position: relative;
      display: flex;
      justify-content: space-between;
    }
    .timeline-event {
      position: relative;
      cursor: pointer;
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      width: 12rem; /* Fixed width for each event container */
    }
    .timeline-dot {
      width: 20px;
      height: 20px;
      background-color: #9ca3af; /* gray-400 */
      border-radius: 50%;
      border: 3px solid var(--border-color); /* gray-50 */
      transition: all 0.3s ease;
      z-index: 10;
    }
    .timeline-event:hover .timeline-dot {
      transform: scale(1.2);
      background-color: #3b82f6; /* blue-500 */
    }
    .timeline-event.active .timeline-dot {
      background-color: #2377ff; /* blue-500 */
      transform: scale(1.3);
      border-color: var(--border-color); /* gray-200 */
    }
    .timeline-year {
      position: absolute;
      top: 1.5rem;
      font-weight: 600;
      font-size: 0.875rem;
      color: var(--blockquote-color);
    }
    .timeline-event.active .timeline-year {
      color: var(--text-color);
      font-weight: 800;
    }

    /* Smooth transition for the details panel */
    #timeline-details {
      transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
      &gt; p {
        &gt; span:first-child {
          display: inline-block;
          font-weight: 800;
          width: 3rem;
        }
      }
    }

    #details-locations {
      span::before {
        content: &quot;, &quot;;
      }
      span:first-child::before {
        content: &quot;&quot;;
      }
    }

    .label {
      display: inline-block;
      width: 3.5rem;
    }
    .oneline {
      margin-top: 0;
      margin-bottom: 0;
    }
    .event-description {
      margin-top: 1rem;
      margin-left: 1rem;
      margin-right: 1rem;
    }
  &lt;/style&gt;
  &lt;!-- Timeline Visualization --&gt;
  &lt;div class=&quot;timeline-container&quot;&gt;
    &lt;div class=&quot;timeline-line&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;timeline-events&quot; class=&quot;timeline-events&quot;&gt;
      &lt;template id=&quot;event-template&quot;&gt;
        &lt;div class=&quot;timeline-event&quot;&gt;
          &lt;div class=&quot;timeline-year label&quot;&gt;&lt;/div&gt;
          &lt;div class=&quot;timeline-dot&quot;&gt;&lt;/div&gt;
        &lt;/div&gt;
      &lt;/template&gt;
      &lt;!-- Events will be dynamically inserted here by JavaScript --&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- Event Details Display --&gt;
  &lt;div id=&quot;timeline-details-container&quot; class=&quot;container&quot;&gt;
    &lt;div id=&quot;timeline-details&quot; class=&quot;preface&quot;&gt;
      &lt;h3 id=&quot;details-title&quot;&gt;&lt;/h3&gt;
      &lt;p class=&quot;oneline&quot;&gt;
        &lt;span class=&quot;label&quot;&gt;When: &lt;/span&gt;&lt;span id=&quot;details-year&quot;&gt;&lt;/span&gt;
      &lt;/p&gt;
      &lt;p class=&quot;oneline&quot;&gt;
        &lt;span class=&quot;label&quot;&gt;Where: &lt;/span&gt;&lt;span id=&quot;details-locations&quot;&gt;&lt;/span&gt;
      &lt;/p&gt;
      &lt;p id=&quot;details-description&quot;&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;script&gt;
    document.addEventListener(&quot;DOMContentLoaded&quot;, function () {
      const timelineData = [
        {
          timePeriod: &quot;17th - Early 19th Century&quot;,
          title: &quot;The American Enlightenment and Colonial Colleges&quot;,
          locations: [
            &quot;Europe&quot;,
            &quot;Boston MA&quot;,
            &quot;Philadelphia PA&quot;,
            &quot;New Haven CT&quot;,
            &quot;Newport RI&quot;,
            &quot;Charleston SC&quot;,
          ],
          description:
            &quot;European Enlightenment ideas, particularly from thinkers like John Locke, migrated to the American colonies, influencing a distinct American intellectual identity focused on reason, self-governance, and scientific progress. This intellectual capital was concentrated in East Coast port cities, which served as nexuses for transatlantic trade and communication. The founding of the nine colonial colleges, such as Harvard, Yale, and the College of Philadelphia, solidified these urban centers as the primary hubs of early American intellect, attracting scholars and students and creating an environment for the dissemination of new ideas.&quot;,
        },
        {
          timePeriod: &quot;1862 &amp; 1890&quot;,
          title: &quot;The Morrill Land-Grant Acts&quot;,
          locations: [&quot;United States&quot;, &quot;Midwest&quot;, &quot;West&quot;, &quot;South&quot;],
          description:
            &quot;The Morrill Acts were a pivotal federal policy that drove the westward and southern migration of intellectual capital. By granting federal lands to states to establish public colleges focused on &#39;agriculture and the Mechanic arts,&#39; the acts spurred the creation of new intellectual centers across the country, particularly in the Midwest and West. This deliberately shifted the focus from the classical education of the East Coast to a more practical, democratized form of knowledge. The Second Morrill Act of 1890 furthered this distribution by mandating the creation of separate institutions for Black students in former Confederate states, leading to the establishment of numerous Historically Black Colleges and Universities (HBCUs) and fostering intellectual capital within African American communities in the South.&quot;,
        },
        {
          timePeriod: &quot;Mid-19th - Early 20th Century&quot;,
          title: &quot;Rise of Midwestern Hubs and Early Immigration&quot;,
          locations: [&quot;Chicago IL&quot;, &quot;Midwest USA&quot;, &quot;Europe&quot;],
          description:
            &quot;The economic and industrial boom of the Midwest, exemplified by Chicago&#39;s rapid growth as a railroad and manufacturing hub, created a new center of intellectual gravity. The founding of institutions like the University of Chicago, with its German-style research focus, attracted scholars and established a high-level intellectual center away from the East Coast. Simultaneously, waves of European immigrants, including a significant number of inventors and scientists like Nikola Tesla, brought their intellectual capital to the U.S., contributing to burgeoning sectors like electricity and chemicals. This represented a significant &#39;brain gain&#39; from Europe, distributing specialized skills across the industrializing nation.&quot;,
        },
        {
          timePeriod: &quot;1930s - 1940s&quot;,
          title: &quot;European Intellectual Migration&quot;,
          locations: [&quot;Europe&quot;, &quot;United States&quot;],
          description:
            &quot;The rise of Nazism and fascism in Europe triggered a mass exodus of scholars, scientists, and artists who sought refuge in the United States. This &#39;intellectual migration&#39; included luminaries from the Frankfurt School and logical empiricists like Rudolf Carnap. These émigrés, many of whom secured positions at elite American universities, caused a significant &#39;brain drain&#39; from Europe and shifted the global academic center of gravity towards the U.S., profoundly enriching American academia, philosophy, and science.&quot;,
        },
        {
          timePeriod: &quot;1944&quot;,
          title: &quot;The G.I. Bill of Rights&quot;,
          locations: [&quot;United States&quot;],
          description:
            &quot;The G.I. Bill dramatically democratized higher education by providing funding for millions of World War II veterans to attend college. This massive influx of students spurred the expansion of universities and educational facilities across the entire nation, not just in established centers. By creating one of the most educated generations in U.S. history, the bill substantially increased the nation&#39;s overall stock of human capital and helped distribute it more widely across the country, fueling the post-war economic boom and the growth of the middle class.&quot;,
        },
        {
          timePeriod: &quot;1945 - 1959&quot;,
          title: &quot;Operation Paperclip&quot;,
          locations: [&quot;Germany&quot;, &quot;United States&quot;],
          description:
            &quot;Operation Paperclip was a clandestine U.S. program that recruited over 1,600 German scientists and engineers after World War II. This was a direct, strategic acquisition of foreign intellectual capital, primarily to bolster U.S. military and aerospace research and to prevent this talent from aiding the Soviet Union. Scientists like Wernher von Braun were pivotal to the U.S. space program. This event represents a highly targeted &#39;brain gain&#39; that transferred specialized technological expertise from Germany directly into U.S. government and defense sectors, accelerating American capabilities during the Cold War.&quot;,
        },
        {
          timePeriod: &quot;Mid-20th Century - Present&quot;,
          title:
            &quot;The West Coast Ascendant: Universities, Silicon Valley, and Aerospace&quot;,
          locations: [&quot;California&quot;, &quot;Silicon Valley CA&quot;, &quot;Southern California&quot;],
          description:
            &quot;A major westward migration of intellectual capital occurred, fueled by massive federal R&amp;D investment, the growth of the University of California system, and elite private universities like Stanford and Caltech. The synergy between these research institutions, venture capital, and federal defense spending gave rise to new, dominant intellectual-industrial centers. This included the aerospace boom in Southern California and the birth of Silicon Valley in Northern California, which became the global epicenter for electronics, semiconductors, and computing. This shift established the West Coast as a leader in a new form of technology-driven intellectual capital.&quot;,
        },
        {
          timePeriod: &quot;1965&quot;,
          title: &quot;The Immigration and Nationality Act of 1965&quot;,
          locations: [&quot;Global&quot;, &quot;United States&quot;],
          description:
            &quot;This act fundamentally reshaped the flow of global intellectual capital into the United States. By abolishing the national origins quota system and creating a preference system for immigrants with specific skills and professions, the law opened the door to highly educated individuals from Asia, Africa, and Latin America. This policy deliberately targeted skilled labor and professionals, resulting in a significant and sustained &#39;brain gain&#39; that enhanced U.S. competitiveness in science and technology. It diversified the sources of intellectual talent and reinforced the U.S.&#39;s position as a magnet for global expertise.&quot;,
        },
        {
          timePeriod: &quot;Late 20th - Early 21st Century&quot;,
          title: &quot;The Rise of Dispersed Tech Hubs&quot;,
          locations: [&quot;Seattle WA&quot;, &quot;Austin TX&quot;, &quot;Research Triangle Park NC&quot;],
          description:
            &quot;Following the Silicon Valley model, new intellectual and tech hubs emerged in geographically diverse locations. This demonstrates a polycentric distribution of intellectual capital rather than a simple westward shift. Seattle became a center for software and e-commerce (Microsoft, Amazon), Austin (&#39;Silicon Hills&#39;) for semiconductors and IT (Dell, Sematech), and North Carolina&#39;s Research Triangle Park for biotech and IT, driven by a collaboration between three major research universities. The success of these hubs illustrates a pattern of regional specialization, often built around the &#39;triple helix&#39; of universities, industry, and government.&quot;,
        },
      ];

      const eventsContainer = document.getElementById(&quot;timeline-events&quot;);
      const eventTemplate = document.getElementById(&quot;event-template&quot;);
      const detailsPanel = document.getElementById(&quot;timeline-details&quot;);
      const detailsTitle = document.getElementById(&quot;details-title&quot;);
      const detailsYear = document.getElementById(&quot;details-year&quot;);
      const detailsLocations = document.getElementById(&quot;details-locations&quot;);
      const detailsDescription = document.getElementById(&quot;details-description&quot;);

      let activeEvent = null;

      // --- Function to create and display the timeline ---
      function buildTimeline() {
        timelineData.forEach((eventData, index) =&gt; {
          const eventContainer = eventTemplate.content.cloneNode(true);
          eventContainer.querySelector(&quot;.timeline-event&quot;).dataset.index = index;
          eventContainer.querySelector(&quot;.timeline-year&quot;).textContent =
            eventData.timePeriod;
          eventsContainer.appendChild(eventContainer);
        });
      }

      // --- Function to update the details panel ---
      function showEventDetails(index) {
        const eventData = timelineData[index];

        // Fade out the old content
        detailsPanel.style.opacity = &quot;0&quot;;
        detailsPanel.style.transform = &quot;translateY(1rem)&quot;;

        setTimeout(() =&gt; {
          // Update content
          detailsTitle.textContent = eventData.title;
          detailsYear.textContent = eventData.timePeriod;
          detailsLocations.replaceChildren(
            ...eventData.locations.map((s) =&gt; {
              const span = document.createElement(&quot;span&quot;);
              span.textContent = s;
              return span;
            })
          );
          detailsDescription.textContent = eventData.description;

          // Fade in the new content
          detailsPanel.style.opacity = &quot;1&quot;;
          detailsPanel.style.transform = &quot;translateY(0)&quot;;
        }, 300); // Wait for fade-out to complete
      }

      // --- Event listener for clicks on the timeline ---
      eventsContainer.addEventListener(&quot;click&quot;, function (e) {
        const clickedEvent = e.target.closest(&quot;.timeline-event&quot;);
        if (!clickedEvent) return;

        const index = clickedEvent.dataset.index;

        // If it&#39;s already active, do nothing
        if (activeEvent === clickedEvent) return;

        // Remove active class from the previous event
        if (activeEvent) {
          activeEvent.classList.remove(&quot;active&quot;);
        }

        // Add active class to the new event
        clickedEvent.classList.add(&quot;active&quot;);
        activeEvent = clickedEvent;

        showEventDetails(index);
      });

      // --- Initial setup ---
      buildTimeline();

      // Automatically select and show the first event on load
      const firstEvent = eventsContainer.querySelector(&quot;.timeline-event&quot;);
      if (firstEvent) {
        firstEvent.classList.add(&quot;active&quot;);
        activeEvent = firstEvent;
        showEventDetails(0);
      }
    });
  &lt;/script&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;h4 id=&quot;hydro-catchment-area&quot;&gt;Hydro-Catchment Area&lt;/h4&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/catchment/reservoir.png&quot; width=&quot;300&quot; alt=&quot;A hydro-catchement area and its adjacent reservoir&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A hydro-catchement area and its adjacent
reservoir&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A hydro-catchment area is a geographic region that collects rainwater
and funnels it into the reservoir. These are natural formations.&lt;/p&gt;
&lt;p&gt;Without the hydro-catchment area the reservoir will starve. The
health, robustness, and vitality of the hydro-catchment area directly
impact the long-term viability of its reservoir.&lt;/p&gt;
&lt;/aside&gt;
&lt;h2 id=&quot;decline&quot;&gt;Decline&lt;/h2&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;Just as a reservoir relies on its hydro-catchment area to replenish
their water supply, intellectual endeavors are similarly dependent on
“intellectual catchment areas” —-regions that gather and channel
information, ideas, and people.&lt;/p&gt;
&lt;p&gt;As a hydro-catchment area’s health dictates the long-term viability
of its reservoir; so does the richness and connectivity of an
intellectual catchment area directly influence the vitality of
intellectual pursuits.&lt;/p&gt;
&lt;p&gt;Without these intellectual catchment areas, the wellspring of
creativity and innovation for a particular field risks drying up.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Over many decades, particularly starting towards the end of the
second world war, the United States has became one of the largest
reservoirs of intellectual capital&lt;a href=&quot;https://xn--izc.com/posts/catchment/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. While the rise of
fascism in Europe drove some precipitation of knowledge into the US in
the 1930s and 1940s &lt;span class=&quot;citation&quot; data-cites=&quot;lassig&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/catchment/#ref-lassig&quot; role=&quot;doc-biblioref&quot;&gt;L{“a}ssig, Simone,
2017&lt;/a&gt;)&lt;/span&gt;, the intellectual dominance that followed in the
decades since the world wars was driven by a positive feedback loop
which made the US increasingly attractive to the best minds of the
world.&lt;/p&gt;
&lt;p&gt;The groundswells of industry established around major universities as
well as billions of dollars of research funding from the NSF, NIH, and
DARPA created prolific centers of intellectual activity. The Immigration
and Nationality Act of 1965 opened the floodgates that were arguably
already partially open to international students and skilled labor from
all over the world. Out of all this emerged ecosystems of collaboration
with regional specializations.&lt;/p&gt;
&lt;p&gt;These ecosystems built between industry, government, and academia are
collectively the US’s intellectual catchment areas. It took centuries to
build what we have now.&lt;/p&gt;
&lt;p&gt;What’s more important than what it is, is how the system sustains
itself.&lt;/p&gt;
&lt;p&gt;And the short answer is that it works because it was working before.
We were in a positive feedback loop.&lt;/p&gt;
&lt;p&gt;Specifically, the fact that the whole world thinks of the United
States as the leader in technology means that all the best minds want to
live and work in the United States. The fact that the conditions were
favorable for skilled immigrants to study, live, and work in the United
States so far means that this dream becomes a reality to millions of
people.&lt;/p&gt;
&lt;p&gt;It’s not just skilled immigration.&lt;/p&gt;
&lt;p&gt;The universities need to continue fostering the thought and
collaboration that breeds innovation. Until this year, this positive
feedback loop has remained stable. But positive feedback loops can break
– especially if one were to violate several of the reasons why the loop
exists in the first place.&lt;/p&gt;
&lt;p&gt;The ongoing threats against these elite universities at the centers
of intellectual catchment areas and the ongoing threats against
immigration will undo what took a century to build.&lt;/p&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-affectedUniversities&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Alan Blinder. (n.d.). &lt;em&gt;Trump Has Targeted These Universities.
Why?&lt;/em&gt; Retrieved July 4, 2025, from &lt;a href=&quot;https://www.nytimes.com/article/trump-university-college.html&quot;&gt;https://www.nytimes.com/article/trump-university-college.html&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-bestColleges1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
BestColleges Staff. (2025, June 10). &lt;em&gt;These Colleges and Universities
Are Cutting Costs Over Federal Funding Freezes&lt;/em&gt;. &lt;a href=&quot;https://www.bestcolleges.com/news/colleges-university-cut-costs-federal-funding-freeze/&quot;&gt;https://www.bestcolleges.com/news/colleges-university-cut-costs-federal-funding-freeze/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-bigImmigrationBlog1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Big Immigration Law Blog. (2025, April 10). &lt;em&gt;The New Risk for Global
Talent: F-1 SEVIS Terminations and Student Visa Revocations&lt;/em&gt;. &lt;a href=&quot;https://www.bigimmigrationlawblog.com/2025/04/the-new-risk-for-global-talent-f-1-sevis-terminations-and-student-visa-revocations/&quot;&gt;https://www.bigimmigrationlawblog.com/2025/04/the-new-risk-for-global-talent-f-1-sevis-terminations-and-student-visa-revocations/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-time1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Charlotte Alter. (2024, April 2). &lt;em&gt;These Are the Students Targeted by
Trump’s Immigration Enforcement Over Campus Activism&lt;/em&gt;. &lt;a href=&quot;https://time.com/7272060/international-students-targeted-trump-ice-detention-deport-campus-palestinian-activism/&quot;&gt;https://time.com/7272060/international-students-targeted-trump-ice-detention-deport-campus-palestinian-activism/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-harvardGazette1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Harvard Staff. (2025, June 12). &lt;em&gt;Federal judge blocks Trump plan to
ban international students at Harvard&lt;/em&gt;. &lt;a href=&quot;https://news.harvard.edu/gazette/story/2025/06/federal-judge-blocks-trump-plan-to-ban-international-students-at-harvard/&quot;&gt;https://news.harvard.edu/gazette/story/2025/06/federal-judge-blocks-trump-plan-to-ban-international-students-at-harvard/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-lassig&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
L{“a}ssig, Simone. (2017). &lt;em&gt;Strategies and Mechanisms of Scholar
Rescue: The Intellectual Migration of the 1930s Reconsidered&lt;/em&gt;.
&lt;em&gt;84&lt;/em&gt;, 769–807.
&lt;/div&gt;
&lt;div id=&quot;ref-massLive1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Melissa Hanson. (2025, June 25). &lt;em&gt;Foreign Harvard students were
detained at Logan Airport, denied visas after Trump proclamation&lt;/em&gt;.
&lt;a href=&quot;https://www.masslive.com/news/2025/06/foreign-harvard-students-were-detained-at-logan-airport-denied-visas-after-trump-proclamation.html&quot;&gt;https://www.masslive.com/news/2025/06/foreign-harvard-students-were-detained-at-logan-airport-denied-visas-after-trump-proclamation.html&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-npr1&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Sequoia Carrillo. (2025, June 5). &lt;em&gt;International students look to the
U.K. instead of the U.S., as Trump squeezes visas&lt;/em&gt;. &lt;a href=&quot;https://www.npr.org/2025/06/05/nx-s1-5415740/trump-international-student-visas-uk-universities&quot;&gt;https://www.npr.org/2025/06/05/nx-s1-5415740/trump-international-student-visas-uk-universities&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;The US is not the &lt;em&gt;largest&lt;/em&gt; reservoir of
intellectual capital. That honor likely goes to China. However in a
number of fields, the US is –or was until recently– the most prolific.&lt;a href=&quot;https://xn--izc.com/posts/catchment/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Act III: Flame</title>
      <link href="https://xn--izc.com/series/structure-of-experience/flame/" />
      <updated>2025-05-07T00:00:00Z</updated>
      <id>https://xn--izc.com/series/structure-of-experience/flame/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;We are prone to anthropomorphizing anything that looks or acts
vaguely lifelike. All the way back in the 1960s, when people were
confronted with a rudimentary chatbot, they were convinced that it
embodied empathy and understanding (&lt;a href=&quot;https://en.wikipedia.org/wiki/ELIZA_effect&quot;&gt;ELIZA effect&lt;/a&gt;)&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Roll forward to the 2020’s and chatbots are substantially more
complicated. Unsurprisingly, people attribute more and more human
qualities to bots. We saw &lt;a href=&quot;https://www.washingtonpost.com/technology/2022/06/11/google-ai-lamda-blake-lemoine/&quot;&gt;people
stake their reputations&lt;/a&gt; on the claim that some AI systems are
sentient and therefore have feelings that might be hurt by humans’
relentless experimentation.&lt;/p&gt;
&lt;p&gt;There are obvious ethical considerations that follow from such
claims. &lt;a href=&quot;https://www.anthropic.com/research/exploring-model-welfare&quot;&gt;Anthropic
recently announced&lt;/a&gt; (April 24, 2025) that this is a question they
wish to explore in earnest.&lt;/p&gt;
&lt;p&gt;Anthropic’s work is very forward looking. Currently, we are nowhere
near an answer to the question of whether LLMs are conscious. However
there are good reasons why they aren’t.&lt;/p&gt;
&lt;p&gt;Before answering the question of whether something is conscious, one
must know what consciousness is. We don’t know what that is yet (see &lt;a href=&quot;https://en.wikipedia.org/wiki/Hard_problem_of_consciousness&quot;&gt;The
hard problem of consciousness&lt;/a&gt;). Our near term goal is to establish
what’s called &lt;a href=&quot;https://en.wikipedia.org/wiki/Neural_correlates_of_consciousness&quot;&gt;neural
correlates of consciousness&lt;/a&gt; – observable phenomena in the human
brain that are highly correlated with the subject’s state of
consciousness. We haven’t yet (as of this writing on May 5, 2025)
achieved this near term goal.&lt;/p&gt;
&lt;p&gt;Short of knowing what brings about subjective experience, people
resort to convoluted experiments like &lt;a href=&quot;https://en.wikipedia.org/wiki/Chinese_room&quot;&gt;the Chinese room&lt;/a&gt;
to eliminate situations where consciousness is absent and to point out
that nothing along the path we are traversing really reaches any
meaningful self-awareness.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/flame/flame.jpg&quot; class=&quot;noinvert&quot; width=&quot;800&quot; alt=&quot;The flame of an imaginary candle. Generated using Gemini.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The flame of an imaginary candle.
Generated using Gemini.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Is this picture of a flame hot? There never was an actual flame in
this instance because this image was generated by AI. The AI may have
seen pictures of many real candles, but it has never felt the warmth of
a candle. It is therefore safe to assume that the sense of heat played
no role in this picture.&lt;/p&gt;
&lt;p&gt;What if we start with a more realistic looking model of a flame. Then
we can calculate how the flame should behave&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;
with time. No matter how detailed this model is, the model does not
constitute a flame. We can crank up the fidelity and accuracy of our
calculations as far up as technology allows, but it will still not burst
into flame&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is where we are with AI and consciousness. We have descriptions
of how to determine the next word in a sequence of words. These
descriptions are extremely detailed and based on unfathomable amounts of
information. They are so complicated that nobody knows how they behave,
so the only way we can find out what they will do is to run them against
some input and see what happens. We know these models can be made even
more complicated than their current, already incredible, complexity.&lt;/p&gt;
&lt;p&gt;But no matter how far we go, we still only have a description and a
thing that can interpret this description. We can increase the
complexity of the description or increase the speed of the interpreter,
but there is no setting on this continuum where information suddenly
becomes self-aware. It is intuitive that the description will not
achieve any physical accomplishment no matter where we take it. So the
mechanism of consciousness must depend on the implementation of the
interpreter. Currently, that too has no “ignite consciousness”
threshold.&lt;/p&gt;
&lt;p&gt;So this post will also end the way Anthropic’s announcement does:&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;“There’s no scientific consensus on how to even approach these
questions or make progress on them. In light of this, we’re approaching
the topic with humility and with as few assumptions as possible. We
recognize that we’ll need to regularly revise our ideas as the field
develops.”&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;— &lt;a href=&quot;https://www.anthropic.com/research/exploring-model-welfare&quot;&gt;Anthropic&lt;/a&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;ELIZA is fascinating in how simple the whole system is
while being seemingly complex. You can play around with some modern &lt;a href=&quot;https://www.masswerk.at/elizabot/&quot;&gt;web-based simulations like this
one&lt;/a&gt;. See if you can figure out how it might be calculating its
responses.&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;This is a very broad area of research. Search for
&lt;em&gt;flame dynamics&lt;/em&gt;. E.g. &lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S001046551830403X&quot;&gt;Flame
simulations with an open-source code - ScienceDirect&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;Technically if the equipment heats up enough, then it
&lt;em&gt;might&lt;/em&gt; actually burst into flame. But that has nothing to do
with the specifics of the flame we are trying to simulate. It can just
as well happen while trying to &lt;a href=&quot;https://web.math.princeton.edu/math_alive/Crypto/Lab2/Factorization.html&quot;&gt;factor
a large prime&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/series/structure-of-experience/flame/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Act I: Meaning</title>
      <link href="https://xn--izc.com/series/structure-of-experience/meaning/" />
      <updated>2025-05-04T00:00:00Z</updated>
      <id>https://xn--izc.com/series/structure-of-experience/meaning/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/meaning/1.excalidraw.png&quot; title=&quot;A meaningless shape&quot; class=&quot;noinvert&quot; alt=&quot;This is a meaning.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;This is a meaning.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It doesn’t look like much because I haven’t told you what it is yet.
That’s going to come in the following paragraphs. All I’ve done is toss
an abstract concept up in the air. It seems pointless, but it gives us a
canvas to paint with meaning later.&lt;/p&gt;
&lt;p&gt;For example, if I tell you that this meaning concerns a feeling –
something very abstract – it suddenly looks a tiny bit different. Now
look at it.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/meaning/2.excalidraw.png&quot; class=&quot;noinvert&quot; alt=&quot;A feeling&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A feeling&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Not all the words I speak will add meaning equally. Some are
digressions that you have learned to ignore like this sentence that
isn’t talking about our thing at all. In one ear and out the other. You
won’t pay much attention to those.&lt;/p&gt;
&lt;p&gt;Still others, like the sentence that is about to follow this one, are
in fact talking about our thing, so you will pay attention to those. Our
meaning, the one we are talking about, is going to be about a feeling –
a calm feeling. Something that you feel when you suddenly run out of
ideas or your mind stops racing and you become aware of the environment
around you.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/meaning/3.excalidraw.png&quot; class=&quot;noinvert&quot; alt=&quot;Calmness&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Calmness&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The feeling you get when you are in the middle of a forest. A calm
forest where you are not worried about any creepy-crawlies. It’s the
afternoon, but not a lot of sunshine is making it through the canopy.
You can smell the moss – it feels wet and earthy even though you know
you can’t smell wet.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/meaning/4.excalidraw.png&quot; class=&quot;noinvert&quot; alt=&quot;A calm forest&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A calm forest&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Unlike two steps ago, these last few sentences were a bit special.
You see, up till now I tossed out a very plain and boring thing in the
air and painted it with a couple of distinct and well understood – if a
bit vague. But in the last paragraph, I made you dip a brush into your
own subjective experience and paint our thing in your mind. The meaning
is now yours and yours alone.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/series/structure-of-experience/meaning/5.excalidraw.png&quot; class=&quot;noinvert&quot; alt=&quot;Lots of different meanings&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Lots of different meanings&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And that’s special because your experiences are not things that can
be communicated to you. We don’t have language for that – because those
experiences cannot be constructed innately. They &lt;em&gt;must&lt;/em&gt; be
communicated to you through your senses. Those bodies have ways of
constructing feelings for you that mere abstract meanings cannot.
However once you have those feelings in yourself, our abstract words
&lt;em&gt;can&lt;/em&gt; conjure them out at will; just like we did when we spoke
about the forest.&lt;/p&gt;
&lt;p&gt;If we had a succinct way to communicate this meaning in one go, we
would have.&lt;/p&gt;
&lt;p&gt;But our language and our facility of communicating ideas which we
stimulate with our language doesn’t afford us such shortcuts. So our
language tends to be very abstract; and sometimes it takes a little
shortcut and conjures up a meaning from the back of the subjects’ mind
like we did with our allusions. Again, these are not always shortcuts.
These are the &lt;em&gt;only&lt;/em&gt; ways in which we can communicate certain
things – things that can only be constructed in one’s head with one’s
senses.&lt;/p&gt;
&lt;p&gt;So to understand these ideas, one must have the right ingredients in
their minds. To create these things in their heads one must experience
things with their senses.&lt;/p&gt;
&lt;p&gt;And if we can’t conjure meaning then we can’t understand each other.
And if we can’t understand each other then we can’t have compassion and
empathy.&lt;/p&gt;
&lt;p&gt;Interestingly, this is how we fundamentally differ from the current
LLMs. You see, they have another problem. They don’t have any
experiences to conjure because they don’t have feelings. So when they
encounter language, they can’t understand what those words mean. But one
thing that they can do is to reach into their vast embeddings and see
&lt;em&gt;how&lt;/em&gt; someone who can feel would have responded. And then they
can respond accordingly. What they conjure isn’t life experience or
feeling, but evidence of others having reacted a certain way to a
certain sequence of ideas.&lt;/p&gt;
&lt;p&gt;Because they can’t construct new feelings, their universe of feeling
will always be limited by what people have felt and reacted to. That way
they can look at those reactions and imitate them. The meanings in your
head are yours alone.&lt;/p&gt;
&lt;p&gt;No one can see your dreams. Especially not the robots.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Intermission - Q1 of 2025</title>
      <link href="https://xn--izc.com/posts/intermezzo-2025/" />
      <updated>2025-05-03T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/intermezzo-2025/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It’s been a while since I’ve published anything here. This is partly
because every time I try to write there is something much more important
and terrible happenning in the world that I’m not qualified to write
about. Everything else including whatever it was that I was trying to
write about seems trivial and inconsequential by comparison.&lt;/p&gt;
&lt;p&gt;Many years ago I’d have said that there is very little evil in the
world and that most people you will meet are good. I still sort of
believe that people are good, but I’m beginning to think that the word
&lt;em&gt;“most”&lt;/em&gt; may not be readily applicable.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/intermezzo-2025/do-not-press.jpg&quot; class=&quot;noinvert&quot; alt=&quot;A big red button labelled DO NOT PRESS is attached to the top of an ominous looking device to which many wires and conduits are attached.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A big red button labelled &lt;strong&gt;DO NOT
PRESS&lt;/strong&gt; is attached to the top of an ominous looking device to
which many wires and conduits are attached.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;School children has this &lt;em&gt;would-you-rather&lt;/em&gt; question about a
big red button.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Hypothetically, if there were a big red button that when pushed
gives you a million dollars, but also kills a random person, would you
press it?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is safe to say that the answer to this question is predominently
&lt;em&gt;yes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;More worryingly, the reward doesn’t need to be nearly that high. It
seems, for some, there doesn’t need to be a reward at all as long as the
person who would be harmed is of a specific race, sexual orientation,
body dysmorphia, where they were born, or religion. There’s enough hate
to take the place of a reward.&lt;/p&gt;
&lt;p&gt;People aren’t born this way. Decades of being conditioned to cast out
a group of people gradually dehumanizes them. With enough rhetoric,
likemindedness, and reinforcement anything can be normalized. Anyone
disagreeing – and is not a member of the outcasts – can be easily
disregarded as being the enemy or at least misguided. Hate becomes
self-sustaining, and can last generations.&lt;/p&gt;
&lt;p&gt;We can win battles or wars, but we are not going to really move
forward as a species unless we figure this one out – how to teach
compassion, and how to reason someone away from hate?&lt;/p&gt;
&lt;p&gt;Contrary to popular opinion I think pushing the hateful away is not a
sustainable solution in the long run. Suppressing hateful behavior
without corrective guidance has historically just made the hateful group
more resentful and even more entrenched in their beliefs. Ultimately
they will – as evidenced in recent events – have enough momentum and
intensity to turn the tables.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Preface</title>
      <link href="https://xn--izc.com/series/structure-of-experience/preface/" />
      <updated>2025-05-01T00:00:00Z</updated>
      <id>https://xn--izc.com/series/structure-of-experience/preface/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Large language models’ ability to mimic human language and show signs
of intelligence is quite strange yet makes sense at the same time. This
series is a very gentle introduction to how they &lt;em&gt;almost&lt;/em&gt; capture
human experience through language and how language is perhaps the
weirdest invention of all.&lt;/p&gt;
&lt;p&gt;It’s going to be a bit of a long ride. Perhaps by the time you read
it I haven’t quite finished the whole series. So you’ll see what looks
like an abrupt ending or missing episodes. They are coming. Just
slowly.&lt;/p&gt;
&lt;p&gt;Onwards …&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Intrinsic and Extrinsic Motivation: An anecdote</title>
      <link href="https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/" />
      <updated>2025-03-22T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/intrinsic-vs-extrinsic.png&quot; class=&quot;noinvert&quot; alt=&quot;Intrinsic vs. extrinsic&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Intrinsic vs. extrinsic&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A long long time ago in a totally hypothetical company that still
exists but only in name, there was a little bit of discontent&lt;a href=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. You see, one of the core values of
the company was its commitment to diversity and inclusion. Rather than
lowering the bar, like how some people think inclusion works, they had
many outreach programs that encouraged women and minorities to take up
STEM. These outreach programs almost necessarily fell on the shoulders
of the women and minorities who were already employed at the company –
after all representation matters. Those who worked on these did so out
of their own passion. They wanted to help others like them.&lt;/p&gt;
&lt;p&gt;Anyone who has worked in tech will tell you it’s a lot of work. This
company’s performance review system attempted to measure the amount and
quality of said work so that they can reward the right people for the
right reasons. Since the company deemed that having a diverse workforce
was in their best interest, ideally they would reward people working
towards that goal. However, the performance review system didn’t measure
anything about volunteer work like what the people doing outreach were
doing.&lt;/p&gt;
&lt;p&gt;So those volunteers were unhappy. All that extra work, often done at
the expense of work that &lt;em&gt;is&lt;/em&gt; measured in the performance review
system, didn’t count for anything when career progress was concerned.
They wanted change.&lt;/p&gt;
&lt;p&gt;The company listened.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Community contributions”&lt;/em&gt; got added to the job descriptions
for people at all levels. Naturally the higher the level, the broader in
scope those contributions were required to be. It was now part of
everyone’s job to make contributions that made the company’s culture
better – be it recruitment, outreach, or whatever.&lt;/p&gt;
&lt;p&gt;The changes to the performance review system was an improvement. But
unintentionally it had other side-effects. Notably, those higher up the
organizational ladder found that their community contributions need to
be commesurate with their status. But starting up an effort that is at
the company or region level was a lot of work. Lucky for them, those
volunteers who were passionate about helping others had already
established programs that were of the right scale.&lt;/p&gt;
&lt;p&gt;So as career focused people are wont to do, they threw their weight
around and effectively took over these outreach programs. The volunteers
were upset. Some left. Others kept working but at a smaller capacity
than what they were before. The career focused people were happy, but
the volunteers were not.&lt;/p&gt;
&lt;p&gt;The outreach programs still existed&lt;a href=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; but
were run by people who were no longer doing it just to help other
people. They were run by people who were trying to help themselves. The
programs faltered; quality went down; the effectiveness of the programs
went downhill. It wasn’t fun or rewarding as it was before.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;There’s a lot of discontent now, but at the time there
was only a little.&lt;a href=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;As of this writing (February of 2025), not any more.&lt;a href=&quot;https://xn--izc.com/posts/intrinsic-motivation-an-anecdote/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Buffer Bloat</title>
      <link href="https://xn--izc.com/posts/buffer-bloat/" />
      <updated>2025-01-03T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/buffer-bloat/</id>
      <content xml:lang="en" type="html">
        &lt;h2 id=&quot;from-here-to-there-on-the-internet&quot;&gt;From Here To There On The
Internet&lt;/h2&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;p&gt;This article is an attempt to explain the concept of buffer bloat to
someone not super familiar with networking. Why would someone not super
familiar with networking need to know about buffer bloat? It was
supposed to point out the effects of trying to &lt;em&gt;hide&lt;/em&gt; or
&lt;em&gt;delay&lt;/em&gt; negative feedback loops.&lt;/p&gt;
&lt;/aside&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;Devices on the internet including your phone, laptop, gaming console,
refridgerator, etc. communicate by exchanging data &lt;em&gt;“packets”&lt;/em&gt;.
They are of course not physical packets. It’s just a useful way to
describe a unit of data sent over a wire or some other network
connection. A packet could be thought of as, say, a single frame in a
video or a small slice of audio, or a couple of paragraphs of text in a
webpage. Devices on the internet will take a big chunk of data (e.g. a
video clip) and break it down into smaller pieces (e.g. a single frame
in the video clip) and then sends each of these pieces along the
network. The receiving device puts the pieces back together to
reconstruct the original thing (e.g. the video clip again)&lt;a href=&quot;https://xn--izc.com/posts/buffer-bloat/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/data.png&quot; alt=&quot;A data packet has some additional information like where it came from and where it is going&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A data packet has some additional
information like where it came from and where it is going&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Each packet has little pieces of extra information to help it get to
where it needs to go. One piece is where it comes from (a source
&lt;em&gt;“address”&lt;/em&gt;). Another is where it is going (a target
&lt;em&gt;“address”&lt;/em&gt;). Devices along the network (like your internet
provider’s networking equipment, satellites, etc.) use this extra
information to correctly route the packets to their intended
destination.&lt;/p&gt;
&lt;p&gt;The network is large and constantly changing. So each device focuses
only on getting the packet at least one step closer to its destination.
The specific journey taken by a packet is unkonwn until it is on its
way.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/network.png&quot; alt=&quot;A source and a target device are connected loosely by a bunch of intermediate connections and devices. In this example the we are only looking at devices that our data packets are likely to encounter along the way. Each device (shown as boxes) and each network connection (shown as pipes between boxes) are different. They differ in how much data they can handle and how fast.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A source and a target device are
connected loosely by a bunch of intermediate connections and devices. In
this example the we are only looking at devices that our data packets
are likely to encounter along the way. Each device (shown as boxes) and
each network connection (shown as &lt;em&gt;pipes&lt;/em&gt; between boxes) are
different. They differ in how much data they can handle and how
fast.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;faster-and-faster&quot;&gt;Faster and Faster&lt;/h2&gt;
&lt;p&gt;So let’s say a video streaming service wants to send your mobile
phone a video. First the streaming service breaks up the video into
small packets. Then it throws all the packets into the network so that
the network can deliver them to your phone.&lt;/p&gt;
&lt;p&gt;If the streaming service pushes data out at exactly the
&lt;em&gt;right&lt;/em&gt; speed and the network doesn’t break, then everything
works out great. All the packets make it to the destination without
hassle. But neither the streaming service nor your phone know what that
&lt;em&gt;right&lt;/em&gt; speed is due to the aforementioned unknowability of the
network.&lt;/p&gt;
&lt;p&gt;Sending too much data can overwhelm some devices or connections in
the network. If a device gets more data than it can handle, it’s likely
that it will start dropping packets until it can catch up.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/speedo.png&quot; alt=&quot;Speedometer. Are we going too slow or too fast or maybe just right?&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Speedometer. Are we going too slow or too
fast or maybe just right?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Sending too little data isn’t great either. The speed might be too
slow for streaming video. The receiving device will underperform. Users
will be confused why their expensive broadband connection doesn’t let
them watch streaming video.&lt;/p&gt;
&lt;p&gt;So how does the device know how much data to send out?&lt;/p&gt;
&lt;h2 id=&quot;flow-control&quot;&gt;Flow Control&lt;/h2&gt;
&lt;p&gt;The mechanisms we use to regulate the flow of data is called
&lt;em&gt;“flow control.”&lt;/em&gt; We are going to look at a method based on
coordination between the sender and the receiver because &lt;em&gt;they are
the only two actors in this scenario that we consider to be reliable and
stable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Different packets can take different paths See the network
connections between &lt;code&gt;C-D&lt;/code&gt; and &lt;code&gt;C-E&lt;/code&gt; in the diagram
above. Either of these paths can take a packet from &lt;code&gt;C&lt;/code&gt; to
&lt;code&gt;F&lt;/code&gt;. Packets going down different paths will arrive at
different times. Also, if the network gets overwhelmed or breaks, then
some of the packets may not make it at all.&lt;/p&gt;
&lt;p&gt;The reciever needs to know how to put the packets back in order and
tell if any are missing.&lt;/p&gt;
&lt;p&gt;To keep track of which packet is which, we can add some new
information to the data packet: let’s call this the &lt;em&gt;sequence&lt;/em&gt;.
As you might imagine, the sequence can start at 1 and count each packet
until the transmission is over. Each packet now has a unique position in
the list of packets.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/data-seq.png&quot; alt=&quot;The same data packet as before, but now it has a sequence field.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The same data packet as before, but now
it has a &lt;em&gt;sequence&lt;/em&gt; field.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Great. But how do we know which packets made it to the other side?
The recipient will need to let us know this information in some sort of
reply. This reply is &lt;em&gt;also&lt;/em&gt; a data packet called an
&lt;em&gt;acknowledgement&lt;/em&gt;. It’s sent from the original recipient back to
the sender.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/data-ack.png&quot; alt=&quot;An example acknowledgement sent back to the sender. In this case the recipient is claiming that packets 4, 6, and 7 were missing. Note that the sender and recipient are switched since this packet is travelling “backwards”.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;An example acknowledgement sent back to
the sender. In this case the recipient is claiming that packets 4, 6,
and 7 were missing. Note that the sender and recipient are switched
since this packet is travelling “backwards”.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Ok so now we have all the information we need to perform some flow
control.&lt;/p&gt;
&lt;p&gt;We can now figure out the optimal rate of data transfer
experimentally using some method like this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Send data as fast as possible.&lt;/li&gt;
&lt;li&gt;If the recipient claims some packets were missing, then resend those
packets and send packets &lt;strong&gt;slower&lt;/strong&gt; than before.&lt;/li&gt;
&lt;li&gt;If the recipient hasn’t complained of missing packets in a while,
try sending them &lt;strong&gt;faster&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;stuck-on-the-wire&quot;&gt;Stuck On The Wire&lt;/h2&gt;
&lt;p&gt;Now imagine you sending data out - a rate of 100 packets per second.
And let’s say it takes one second for a packet to get to the other side.
Just before the end of the first second, the destination hasn’t received
the first packet yet. But the sender has sent 100 packets.&lt;/p&gt;
&lt;p&gt;Where are the packets?&lt;/p&gt;
&lt;p&gt;We call this &lt;em&gt;“data on the wire’&lt;/em&gt;. Some data is indeed on the
wire literally, but that tends to be a tiny amount. Most of the data on
the wire is actually at each of the devices along the way either being
received, or waiting to be sent.&lt;/p&gt;
&lt;p&gt;So once we factor in the equipment in the middle, your path to the
destination looks a little like this:&lt;/p&gt;
&lt;p&gt;The device sees some data come in, stores it, figures out where to
send it next, and sends it on its way. There could be other stuff these
boxes could be doing, but that’s something for another post.&lt;/p&gt;
&lt;p&gt;So from the perspective of a single box the world looks a bit like
this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/network-with-data.png&quot; alt=&quot;The source has sent a bunch of packets. For a moment in time all the packets are either being transmitted somewhere or are waiting to be transmitted out of some device on the internet.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The source has sent a bunch of packets.
For a moment in time all the packets are either being transmitted
somewhere or are waiting to be transmitted out of some device on the
internet.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If this is the limit for the network and the sender keeps sending
more packets, then there’s no room for the packet. So it gets
&lt;em&gt;“dropped”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It is common for a device to be at the border of a “good” network and
a “not”good” network. The goodness here is the amount of data that can
be stuffed into it.&lt;/p&gt;
&lt;p&gt;When a burst of data comes along, not much data can be stuffed into
the small pipe before no more can fit.&lt;/p&gt;
&lt;p&gt;As mentioned before, this means that the sender will need to
&lt;em&gt;re-send&lt;/em&gt; the dropped packets and also slow down the rate of
data. Given enough time the rate of data transfer will approach the
throughput of the smallest pipe along the way.&lt;/p&gt;
&lt;h2 id=&quot;buffer-bloat&quot;&gt;Buffer Bloat&lt;/h2&gt;
&lt;p&gt;Some folks looked at this setup and decided to improve things. There
are some valid reasons for doing what they did – which is why so many
people did this. But it didn’t quite have the intended effect.&lt;/p&gt;
&lt;p&gt;So, what was the thing they did? They added
&lt;strong&gt;buffering&lt;/strong&gt;. Too much of it.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;buffer&lt;/em&gt; is a resevoir where excess packets can be kept
until the next link in the network is ready to accept more. What this
means is that every device along the way is trying to do flow control by
storing and resending packets instead of letting the sender know that
packets are getting dropped.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/network-with-buffer.png&quot; alt=&quot;Device B is dropping all excess packets into a buffer.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Device &lt;code&gt;B&lt;/code&gt; is dropping all
excess packets into a buffer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As before, let’s say the sender is sending 200 packets every second.
The network still can only transfer 100. The excess packets – another
100 of them – gets tossed into the buffer.&lt;/p&gt;
&lt;p&gt;What happens just one second later?&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/bob-1.png&quot; alt=&quot;A very next packet – which we are calling Bob enters the network. The buffer contains 100 packets. The rest of the network also has 100 packets queued.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A very next packet – which we are calling
&lt;em&gt;Bob&lt;/em&gt; enters the network. The buffer contains 100 packets. The
rest of the network also has 100 packets queued.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The very next packet – let’s call it &lt;em&gt;Bob&lt;/em&gt; – that the sender
tosses into the network will end up in the buffer since &lt;code&gt;B&lt;/code&gt;
is still waiting for some of the first 100 packets to get past
&lt;code&gt;C&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/bob-2.png&quot; alt=&quot;Bob immediately gets tossed into the buffer. It is now the last packet in the buffer.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Bob immediately gets tossed into the
buffer. It is now the last packet in the buffer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Bob is the last packet in the buffer and must wait for all the other
packets in the buffer to be send before it will get queued to sent
out.&lt;/p&gt;
&lt;p&gt;In another second, the first 100 packets make it to the target, and
now the 100 packets that were in the buffer are back on the wire.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/bob-3.png&quot; alt=&quot;Bob is still in the buffer, but it is now the very next packet to get fished out and tossed back into the network.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Bob is still in the buffer, but it is now
the very next packet to get fished out and tossed back into the
network.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Bob is still in the buffer but it’s the next one in line to get back
on the network.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/buffer-bloat/bob-4.png&quot; alt=&quot;Hurray! Bob finally makes it to the destination.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Hurray! Bob finally makes it to the
destination.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Once back on the network it will take another second for Bob to reach
the target.&lt;/p&gt;
&lt;p&gt;Even under ideal conditions eventually the system settles on a new
equilibrium with one difference.&lt;/p&gt;
&lt;p&gt;The length of time it takes for the data packets to make their way to
the destination is much larger. Packets accumulate in buffers along the
network. Each buffer adds an additional delay for the packet.&lt;/p&gt;
&lt;p&gt;Overall the throughput of the network is the same. But latency – the
time it takes for a packet to get to the destination – is much
larger.&lt;/p&gt;
&lt;p&gt;The effect is even worse in practice because this setup resists any
attempt at flow control. It delays the discovery of actual
throughput.&lt;/p&gt;
&lt;p&gt;This phenomenon is called &lt;strong&gt;buffer bloat&lt;/strong&gt;.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;This is obviously a massive oversimplification. But
doesn’t change the thesis presented next.&lt;a href=&quot;https://xn--izc.com/posts/buffer-bloat/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Fourteen Years</title>
      <link href="https://xn--izc.com/posts/fourteen-years/" />
      <updated>2024-12-31T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/fourteen-years/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It’s been fourteen years since I joined Google. Much has happened
since then, and people think the old Google is dead. This is somewhat
correct.&lt;/p&gt;
&lt;p&gt;One way to understand what is happening is to compare and contrast
the Google of yore and the present (as of late 2024) Google.&lt;/p&gt;
&lt;h3 id=&quot;from-illegal-flower-tribute&quot;&gt;From Illegal Flower Tribute&lt;/h3&gt;
&lt;p&gt;Perhaps the most defining moment for Google around 2010 was Google
Search’s exit from China. &lt;a href=&quot;https://www.technologyreview.com/2018/12/19/138307/how-google-took-on-china-and-lost/&quot;&gt;The
reasons for the exit and the aftermath&lt;/a&gt; are many. The high level
reason was due to non-capitulance to the Chinese government’s demands
for censorship and compromising user data.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/9/9c/IllegalFlowerTribute1.jpg&quot; class=&quot;noinvert&quot; alt=&quot;Illegal flower tribute on Wikipedia (CC-By-SA 3.0)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Illegal_flower_tribute&quot;&gt;Illegal
flower tribute on Wikipedia&lt;/a&gt; (&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0/&quot;&gt;CC-By-SA
3.0&lt;/a&gt;)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In addtion, Google’s hand was forced by &lt;a href=&quot;https://en.wikipedia.org/wiki/Operation_Aurora&quot;&gt;Operation
Aurora&lt;/a&gt;, a cyber attack on multiple US based companies including
Google orchestrated by Chinese state actors.&lt;/p&gt;
&lt;p&gt;The fascinating accounts of the events surrounding Operation Aurora
is covered in a documentary called “Hacking Google”.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/przDcQe6n5o?si=zQykFdvQP9FSHtZ2&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;
&lt;/iframe&gt;
&lt;figcaption&gt;
Hacking Google - YouTube
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Amazon and Microsoft were in a similar situation as Google. But they
were unwilling to turn away from access to the Chinese market. There was
a palpable sense of pride that we were working for the right
company.&lt;/p&gt;
&lt;h3 id=&quot;to-project-nimbus&quot;&gt;To Project Nimbus&lt;/h3&gt;
&lt;p&gt;Time changes everything.&lt;/p&gt;
&lt;p&gt;Eight years later Google reneged on its stance against censorship by
attempting to build a censored search engine called &lt;a href=&quot;https://en.wikipedia.org/wiki/Dragonfly_(search_engine)&quot;&gt;Project
Dragonfly&lt;/a&gt;. The seeds of capitulance was well under way by this point
despite the fact that the censored search engine project was ultimately
dropped.&lt;/p&gt;
&lt;p&gt;Fast-forward a few more years and we get to &lt;a href=&quot;https://en.wikipedia.org/wiki/Project_Nimbus&quot;&gt;Project Nimbus&lt;/a&gt;.
Google signed the contract despite warnings by its lawyers that &lt;a href=&quot;https://www.nytimes.com/2024/12/03/technology/google-israel-contract-project-nimbus.html?unlocked_article_code=1.mU4.GWhH.uw8jj2kv7n-n&amp;amp;smid=url-share&quot;&gt;&lt;em&gt;“Google
Cloud services could be used for, or linked to, the facilitation of
human rights violations…”&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One could argue that tools like Google Cloud services should be
value-neutral. But even then, what matters here is that Google
intentionally changed the terms-of-use for this contract to allow uses
that were explicitly called out as going against Google’s values.&lt;/p&gt;
&lt;h3 id=&quot;thats-where-we-are&quot;&gt;That’s Where We Are&lt;/h3&gt;
&lt;p&gt;And that’s where we are right now.&lt;/p&gt;
&lt;p&gt;Google has had some rough years during which its relationship with
the rest of the tech ecosystem and the world in general has changed. The
old &lt;em&gt;“focus on the user and all else shall follow”&lt;/em&gt; matra no
longer applies. The company’s focus is now exclusively inwards where the
fact that something benefits everyone is no longer justification to
continue working on it. For example, &lt;a href=&quot;https://techcrunch.com/2024/05/01/google-lays-off-staff-from-flutter-dart-python-weeks-before-its-developer-conference/&quot;&gt;Google
laid off most of the core Python team&lt;/a&gt;. While it may seem like a move
towards cheaper labor, it is more than that. The previous Python team
were also industry veterans who were effectively in the service of the
broader Python community far beyond Google. The replacements are people
who are tasked with maintaining internal tooling and not much else.&lt;/p&gt;
&lt;p&gt;Google is no longer the giant benefactor of technology for everyone.
However it’s still better than the other big tech companies. I keep
telling myself that.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>I Moved This Blog To Eleventy</title>
      <link href="https://xn--izc.com/posts/moved-to-eleventy/" />
      <updated>2024-12-13T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/moved-to-eleventy/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Astute observers of this blog may have noticed that the blog looks
suspiciously different lately. That’s because I changed the static site
generator I was using.&lt;/p&gt;
&lt;p&gt;Previously the &lt;a href=&quot;https://xn--izc.com/posts/how-this-blog-works/&quot;&gt;static site
generator I used&lt;/a&gt; was &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;. This
arrangement worked for a while but it had some shortcomings.&lt;/p&gt;
&lt;h2 id=&quot;growing-pains&quot;&gt;Growing Pains&lt;/h2&gt;
&lt;p&gt;I was using &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc&lt;/a&gt; to convert
Markdown to HTML. Hugo’s support for Pandoc had some limitations. For
example, you can’t specify options for Pandoc or use a bibliography.
When I moved the blog to Hugo, I lost some of these features. Attempting
to close the gap I authored a &lt;a href=&quot;https://github.com/gohugoio/hugo/pull/7529&quot;&gt;patch that added
support for configuring Pandoc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pandoc is extensible via filtering the AST of a document through a
series of programs which can modify it. There is no restrction on the
kinds of programs that you can use.&lt;/p&gt;
&lt;p&gt;If Hugo allowed configuring all this via frontmatter, that may
introduce some tricky security issues.&lt;/p&gt;
&lt;p&gt;Say you download a Hugo theme from the web and try to build your
site. A theme could include frontmatter that causes Pandoc to run an
unsafe binary. That’s not great. So it is understandable that this kind
of feature isn’t a part of Hugo proper&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.
While my patch worked, it was safe only because I controlled every
aspect of the blog.&lt;/p&gt;
&lt;p&gt;While tinkering on this was fun, it created an additional headache.
Namely, whenever and whereever I wanted to build my blog, I had to
maintain a custom build of Hugo. After moving my build a couple of times
maintaining a custom build became a painful chore.&lt;/p&gt;
&lt;h2 id=&quot;the-exodus&quot;&gt;The Exodus&lt;/h2&gt;
&lt;p&gt;So started the process of looking for an easy-to-use static site
generator (hereafter SSG). My requirements were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The SSG should support Markdown.&lt;/li&gt;
&lt;li&gt;Markdown should support some of the Pandoc features I was using, or
at least have the flexibility to extend support for those features.&lt;/li&gt;
&lt;li&gt;Making this work should not require any custom patches.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; was &lt;em&gt;almost&lt;/em&gt; a
no-brainer. People had high praise for it, including developer relations
folks at Google. So I felt like that would be an easy move.&lt;/p&gt;
&lt;p&gt;Eleventy’s Mardown support is based on &lt;a href=&quot;https://github.com/markdown-it/markdown-it&quot;&gt;Mardown-It&lt;/a&gt;. One
thing that I liked about Markdown-It from the start is that there
appeared to be people who are extending it to support various features
of Pandoc. In fact I found plugins for basically all Pandoc features
that I used in this blog. Everything was looking quite rosy.&lt;/p&gt;
&lt;h2 id=&quot;templating&quot;&gt;Templating&lt;/h2&gt;
&lt;h3 id=&quot;webc-eleventy-is-broken&quot;&gt;WebC + Eleventy Is Broken&lt;/h3&gt;
&lt;p&gt;Eleventy supports a templating language called &lt;a href=&quot;https://www.11ty.dev/docs/languages/webc/&quot;&gt;WebC&lt;/a&gt;. It follows
the web-component way of defining layouts, but can avoid much of the
custom element overhead by opportunistically generating plain HTML. I
had already accepted that switching the SSG meant rewriting layout
templates, and using web components to do that seemed like a good idea&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A couple of standalone WebC based templates worked fine. But the
moment I had nested templates, Eleventy hung and eventually crashed. I
didn’t want to go on a side quest to debug it, and ultimately that
would’ve likely led to be violating the “no local patches” rule. So that
was that for WebC. If WebC was more robust or just worked, it would have
been my choice of template engine.&lt;/p&gt;
&lt;p&gt;One cool feature of using WebC with Eleventy is that bundling works
trivially. For example, if you have a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag or
a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag in a component, WebC automatically
pulls the content into the relevant bundles. All other templating
engines supported in Eleventy (save for third-party engines that I
didn’t try) require manual labor to get stuff into the bundles.&lt;/p&gt;
&lt;h3 id=&quot;nunjucks-eleventy-works&quot;&gt;Nunjucks + Eleventy Works&lt;/h3&gt;
&lt;p&gt;The next templating language I looked at was Nunjucks. I had briefly
looked at Liquid as well, but for my purposes Nunjucks and Liquid seemed
to be quite similar. Nunjucks won out because it had safer defaults&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;handrolling&quot;&gt;Handrolling&lt;/h2&gt;
&lt;h3 id=&quot;pandoc-again&quot;&gt;Pandoc Again&lt;/h3&gt;
&lt;p&gt;I tried to rely only on Markdown-It for this blog. But very soon I
had a big stack of extensions to support the various features I needed,
like supporting &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s, bibliography, and attributes.
While the Markdown-It ecosystem is extensive, it also introduces a lot
of confusion. For example, there are multiple packages that all provide
the same functionality and &lt;em&gt;also based on the same base package&lt;/em&gt;.
Keeping track of all this was starting to be a pain. Also, I had trouble
getting block level containers working.&lt;/p&gt;
&lt;p&gt;After a while I decided not to waste time trying to replicate
features that already existed in Pandoc. So I wrote a little library
that invoked Pandoc within Eleventy to convert Markdown to HTML. It was
a little slower, but worked out great.&lt;/p&gt;
&lt;h3 id=&quot;bundling-files&quot;&gt;Bundling Files&lt;/h3&gt;
&lt;p&gt;While it is possible to add content to bundles (like CSS and JS),
curiously it was not possible to stuff files into said bundles. The
suggested method was to do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  {% css %}
    {% include &amp;quot;some-file.css&amp;quot; %}

    body {
        // other CSS.
    }
  {% endcss %}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This seems like a good idea, but there is one crucial issue: &lt;em&gt;The
contents of the included file (&lt;code&gt;some-file.css&lt;/code&gt; in the example
above) is also processed by the same templating engine&lt;/em&gt;. If the file
doesn’t contain any sequences that look like template tokens, then we
are good. But this is asking for trouble.&lt;/p&gt;
&lt;p&gt;So I wrote a custom tag called &lt;code&gt;bundleFile&lt;/code&gt; that can take
the contents of a file and stuff it directly into a bundle. The earlier
example now looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  {% bundleFile &amp;quot;some-file.css&amp;quot; %}

  {% css %}
    body {
        // other CSS
    }
  {% endcss %}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;sassy&quot;&gt;SASSy&lt;/h3&gt;
&lt;p&gt;Eleventy doesn’t support SASS out of the box, but there are examples
in the documentation for how you can set it up. But all of the examples
assume that you have SASS or SCSS files that you are going to conver to
CSS, and then serve without bundling. I wanted to be able to compile
SASS and stuff the resulting CSS into a bundle.&lt;/p&gt;
&lt;p&gt;So alongside the &lt;code&gt;bundleFile&lt;/code&gt; shortcode, I added a
&lt;code&gt;bundleScss&lt;/code&gt; shortcode so I can do stuff like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   {% bundleScss &amp;quot;my-styles.scss&amp;quot; %}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;katex&quot;&gt;Katex&lt;/h3&gt;
&lt;p&gt;I like Katex for my math typesetting. Pandoc supports it out of the
box. But the rendered HTML needs to invoke Katex in the client to render
the math. I wanted to avoid this step entirely and try to render Katex
on the server.&lt;/p&gt;
&lt;p&gt;This was a pain to do with Hugo, but since Eleventy was alredy runing
in Node, server-side rendering is a breeze.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall I found Eleventy fun to work with. My gripes are mostly with
the documentation which lacks a reference. It’s a pain to go through
tutorial-like documents to find out what exactly gets passed to a
shortcode or what to do when a shortcode adds a dependency. I made way
too many trips to the 11ty GitHub repo. The right number of required
visits should be zero.&lt;/p&gt;
&lt;p&gt;In the coming weeks I’ll package Eleventy Pandoc support and some of
the shortcodes so others can use them.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;There are ways to mitigate this problem. For example, we
could restrict which flags can be inherited from themes, or require that
certain options can only be set from the top level
&lt;code&gt;hugo.yaml&lt;/code&gt; file that the user controls.&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;Not quite all the way true because use of shadow DOM and
custom elements was not a requirement.&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;The defaults I’m referring to is what happens with a tag
like &lt;code&gt;{{ foo }}&lt;/code&gt; where the contents of the variable
&lt;code&gt;foo&lt;/code&gt; would be inserted into the document. Nunjucks will
treat the contents as unsafe and requires manually opting into unsafe
injection via &lt;code&gt;{{ foo | safe }}&lt;/code&gt;. Liquid will insert the
contents with no escaping.&lt;a href=&quot;https://xn--izc.com/posts/moved-to-eleventy/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Proof of Work</title>
      <link href="https://xn--izc.com/posts/proof-of-work/" />
      <updated>2024-07-12T14:56:15Z</updated>
      <id>https://xn--izc.com/posts/proof-of-work/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;preface&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Proof_of_work&quot;&gt;Proof-of-work&lt;/a&gt;
refers to a set of methods by which some entity (a person or a
computational system) offers proof that the entity performed a
substantial amount of work. Hereafter, I’ll assume that you—dear
reader—are somewhat familiar with the concept.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Measures like proof-of-work (PoW) are a necessity in
&lt;strong&gt;intentionally slowing down&lt;/strong&gt; otherwise free and
uncontrolled operations. PoW’s most extensive critique is the resulting
high resource consumption that lacks a corresponding commensurate
positive contribution.&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;Working with a poorly thought-out, or overengineered technology
stack, or an overly bureaucratic organization is &lt;em&gt;also a form of
proof-of-work&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This claim seems harsh, but even the intentionality of PoW can be
observed in organizations.&lt;/p&gt;
&lt;p&gt;The first tool people reach for wherever some form of mismatched
trust exists is to introduce bureaucracy. This approach makes sense
because what better way to prevent abuse of authority than to make the
person at a lower trust level ask for permission from someone with a
higher trust level? So, each trust issue one encounters results in one
more approval hurdle – affectionately referred to sometimes as a
“governance gate” or an “approval gate.”&lt;/p&gt;
&lt;p&gt;Now, take a step back and imagine how the proliferation of approval
gates plays out in a large organization like Google. All organizational
activity now involves debilitating bureaucratic overhead. Proliferation
of approvals also have the effect of piling on the responsibility of
approving upon people who are either unqualified to sufficiently assess
the request or simply have no time to go through each in detail.&lt;/p&gt;
&lt;p&gt;Unless each approval gate adds substantial value or prevents harm,
each such approval decays into proof-of-work –&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;the only point of getting the approval is to show that you have gone
through the work of getting the approval.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Bad frameworks and tech stacks have the same effect. Onboarding onto
such a stack is a time-wasting nightmare where people learn
non-transferrable skills that they will most likely only use once. Each
step in getting something done involves putting together poorly
documented and poorly designed pieces and trying to express business
logic in leaky abstractions that muddle the separation between intent
and implementation. Sprikle an inordinate amount of approval gates on
top, and you have our modern large tech company.&lt;/p&gt;
&lt;p&gt;The outcome of weeks of struggle is the same as what is achievable
within a matter of hours with a better tech stack. You haven’t produced
work; you’ve only produced proof of work. The outcome isn’t commensurate
with the effort.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>How to Solve a Problem in Three Steps</title>
      <link href="https://xn--izc.com/posts/how-to-solve-a-problem-in-three-steps/" />
      <updated>2024-07-08T01:09:29Z</updated>
      <id>https://xn--izc.com/posts/how-to-solve-a-problem-in-three-steps/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;One fun thing with having kids is that you get to repeat all the old
stupid jokes to a brand new audience.&lt;/p&gt;
&lt;p&gt;Here’s one:&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;How do you put an elephant in a refridgerator in three steps?&lt;/p&gt;
&lt;figcaption&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Open the door.&lt;/li&gt;
&lt;li&gt;Put elephant in the refridgerator.&lt;/li&gt;
&lt;li&gt;Close the door.&lt;/li&gt;
&lt;/ol&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It’s funny because the purported “answer” doesn’t address any of the
important questions raised by the initial question; not the least of
which regards the mismatch in geometry between a &lt;em&gt;normal&lt;/em&gt;
refridgerator (a household one that immediately springs to the minds of
the audience) and the average live elephant. It’s funny to us becuase we
are familiar with both of these concepts enough to immediately see the
problem. So we immediately prioritize the critical concerns.&lt;/p&gt;
&lt;p&gt;We all get it. But then we are somehow completely blind to the fact
that …&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;… &lt;strong&gt;this is what our OKRs look like after a planning
sprint.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;At Google, as it is with many other large and aging tech companies,
planning of this sort happens in middle management.&lt;/p&gt;
&lt;p&gt;The requisite attributes for doing long arc planning are …&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;… &lt;strong&gt;authority, domain expertise, and ability to
strategize&lt;/strong&gt;. Choose (at most) two.&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/how-to-solve-a-problem-in-three-steps/triangle-of-doom.png&quot; alt=&quot;Authority, domain expertise, and ability to plan: Choose (at most) two.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Authority, domain expertise, and ability
to plan: Choose (at most) two.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Domain expertise&lt;/strong&gt; concerns the understanding of the
problem area that is being tackled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ability to plan&lt;/strong&gt; (or strategize) covers not just
having a vision, but also enough understanding of the tools that are
available to derive a set of strategies that will achieve a desirable
goal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authority&lt;/strong&gt; is the propety of being in the right
place in the organizational hierarchy to exert control over a group of
people who are capable of executing on the strategies. I.e. being in
management at the right level.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In tech, people get to management either by being promoted out of
their zone of competence or by bullshitting their way up the management
chain. Hence the distribution of the &lt;em&gt;authority&lt;/em&gt; attribute
doesn’t necessarily correlate with either of the other two attributes&lt;a href=&quot;https://xn--izc.com/posts/how-to-solve-a-problem-in-three-steps/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;sidenote-host-1&quot;&gt;
&lt;p&gt;So you end up with a layer of middle management that share the
&lt;em&gt;authority&lt;/em&gt; attribute, but at most one of the other two.&lt;/p&gt;
&lt;/div&gt;
&lt;aside class=&quot;sidenote-1&quot;&gt;
&lt;p&gt;Rarely someone will get to a place where they have all the attributes
combined. When this happens it is glorious. You can tell when such
people are in charge even without knowing who the people are. In these
organizations, you will find sensible decisions being made, people
working under realistic timelines, and towards goals that are clearly
achievable through the strategies that they are executing upon. It is
truly a joy to work in such an organization.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;But in most cases “planning sprint” is code for “prepare for damage
control” for those who have &lt;em&gt;domain expertise&lt;/em&gt; and &lt;em&gt;ability to
plan&lt;/em&gt; attributes but not the &lt;em&gt;authority&lt;/em&gt; attribute.&lt;/p&gt;
&lt;p&gt;When people who understand neither refridgerators or elephants decide
to solve problems, the outcome usually looks like the joke we mentioned
before; but with the added injury of unrealistic timelines.&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;Worse, when the strategies are spelled out without understanding the
problem or the purpose of a strategy, the outcome is that those those
doing the work &lt;strong&gt;must frame their work in terms of putting
something into a refridgerator in three steps&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This process is extra fun when the planners have decided to put not
one but &lt;strong&gt;two&lt;/strong&gt; things in the refridgerator without being
specific about what they are. We know one of those things &lt;em&gt;must&lt;/em&gt;
be an elephant for the long term viability of the product, but the other
one could be an orange for all we care. So the workers now have to frame
&lt;em&gt;“solving the elephant”&lt;/em&gt; in terms of &lt;em&gt;“putting the elephant in
the refridgerator”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But the middle management layer continues to consider the orange and
the elephant as being roughly equal problems. Hence &lt;a href=&quot;https://www.warp.dev/blog/problems-with-promotion-oriented-cultures&quot;&gt;those
who play the ladder game&lt;/a&gt; know to work on the orange and not touch
the elephant.&lt;/p&gt;
&lt;p&gt;It is surprising how few good decisions need to be made in order to
keep a multi-billion dollar enterprise chugging along – at least as far
as investors are concerned. You should begin to understand why a company
with so many smart people and so many brilliant creations can make so
many self-defeating mistakes.&lt;/p&gt;
&lt;p&gt;What is not suprising is the amount of fat that constitutes the
middle management of these companies. The &lt;a href=&quot;https://brucefwebster.com/2008/04/15/the-wetware-crisis-the-themocline-of-truth/&quot;&gt;thermocline
of truth&lt;/a&gt; ensures that those looking down from the top will never see
the fat for what it is.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;I can attest to the fact that there are people who only
have the &lt;em&gt;authority&lt;/em&gt; attribute. It is a thing.&lt;a href=&quot;https://xn--izc.com/posts/how-to-solve-a-problem-in-three-steps/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Asian Is Not a Useful Category</title>
      <link href="https://xn--izc.com/posts/asians-is-not-a-useful-category/" />
      <updated>2024-07-04T16:34:41Z</updated>
      <id>https://xn--izc.com/posts/asians-is-not-a-useful-category/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;preface&quot;&gt;
&lt;p&gt;Asking if someone is &lt;em&gt;“Asian”&lt;/em&gt; in a question of ethnicity or
demographics or pretty much any context is bad. There is no reasonable
conclusion you can arrive at about a person based on the fact that they
are &lt;em&gt;“Asian”&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Without knowing anything about the precise demographic breakdown if
you were to learn that a group of people consists of 10% Asians what can
you confidently conclude? What possible useful thing can you derive from
this information?&lt;/p&gt;
&lt;p&gt;First of all, let’s have a look at a map:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/asians-is-not-a-useful-category/map-of-asia.png&quot; width=&quot;512&quot; alt=&quot;Map of Asia – Cacahuate, amendments by Peter Fitzgerald, Globe-trotter, Joelf, and Texugo, CC BY-SA 4.0, via Wikimedia Commons&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Map of Asia – Cacahuate, amendments by
Peter Fitzgerald, Globe-trotter, Joelf, and Texugo, &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0&quot;&gt;CC BY-SA 4.0&lt;/a&gt;,
via Wikimedia Commons&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Here’s a &lt;em&gt;partial&lt;/em&gt; list of countries that are in Asia (based
on &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_sovereign_states_and_dependent_territories_in_Asia&quot;&gt;this
Wikipedia article&lt;/a&gt; and includes contested territories):&lt;/p&gt;
&lt;p&gt;Abkhazia, Afghanistan, Armenia, Azerbaijan, Bahrain, Bangladesh,
Bhutan, Brunei, Cambodia, China, Cyprus, East Timor, Egypt, Georgia ,
Hong Kong, India, Indonesia, Iran, Iraq, Israel, Japan, Jordan,
Kazakhstan, Kuwait, Kyrgyzstan, Laos, Lebanon, Macau, Malaysia,
Maldives, Mongolia, Myanmar, Nepal, North Korea, Northern Cyprus, Oman,
Pakistan, State of Palestine, Philippines, Qatar, Russia, Saudi Arabia,
Singapore, South Korea, South Ossetia, Sri Lanka, Syria, Taiwan,
Tajikistan, Thailand, Turkey, Turkmenistan, United Arab Emirates,
Uzbekistan, Vietnam, and Yemen. {.smaller}&lt;/p&gt;
&lt;p&gt;So if you pictured a room with a bunch of Palastenian, Chinese,
Philipino, Russian, Indian, and Japanese people you would be kind-of
right. But what do Asians look like anyway?&lt;/p&gt;
&lt;p&gt;The point is, Asia is a big place. There are many
countries/states/territories. There are many races, religions,
languages, phenotypes.&lt;/p&gt;
&lt;div class=&quot;quotable&quot;&gt;
&lt;p&gt;There is so much variety in &lt;em&gt;“Asia”&lt;/em&gt; that any conclusion you
would make based on a person or group of people being &lt;em&gt;“Asian”&lt;/em&gt;
will be wrong.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Please stop asking people if they are Asian.&lt;/p&gt;
&lt;h2 id=&quot;so-what-should-i-ask-instead&quot;&gt;So what should I ask instead?&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don’t ask in the first place&lt;/strong&gt; – if not absolutely
necessary. This question is asking for trouble.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;“I prefer not to say”&lt;/em&gt; should always be one of
the options&lt;/strong&gt;. While there are legitimate reasons why you would
ask for some demographic information from a person, always give an
opt-out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Figure out what you actually want to know&lt;/strong&gt;.
Knowing if someone is Asian is not going to give you that information
for reasons stated above. But knowing what you want to know will lead
you to a better question.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Perhaps &lt;em&gt;white&lt;/em&gt;/&lt;em&gt;black&lt;/em&gt;/&lt;em&gt;other&lt;/em&gt; is all you need
for a question about ethnicity.&lt;/li&gt;
&lt;li&gt;For nationality, provide a list of countries but don’t assume
anything about what that person looks like or what language they speak
or what religions they might follow.&lt;/li&gt;
&lt;li&gt;For geography, at worst ask for a region within Asia&lt;a href=&quot;https://xn--izc.com/posts/asians-is-not-a-useful-category/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;
instead of just Asia. And for that matter, the same goes for other
continents.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If “Asian” still remains as one of the response choices for your
question, you are doing something wrong. Not even Google internally gets
this part right. Give up. Don’t ask if someone is “Asian”.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;See the UN’s &lt;a href=&quot;https://unstats.un.org/unsd/methodology/m49/&quot;&gt;Standard country or
area codes for statistical use (M49)&lt;/a&gt; for a list of geographic
regions and various groupings of countries.&lt;a href=&quot;https://xn--izc.com/posts/asians-is-not-a-useful-category/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>The Have-Loop</title>
      <link href="https://xn--izc.com/posts/have-loop/" />
      <updated>2024-06-24T01:45:28Z</updated>
      <id>https://xn--izc.com/posts/have-loop/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/have-loop/have.png&quot; alt=&quot;The have loop is a positive feedback self-loop showing the effects of possessing something of limited supply.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The have loop is a positive feedback
self-loop showing the effects of possessing something of limited
supply.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This is the Have-loop.&lt;/p&gt;
&lt;p&gt;Positive feedback loops are neither new nor rare. The ones we are
concerned with, however, are those where possessing one thing leads to
possessing more of the same thing. Even more specifically, the have-loop
concerns itself with possessing something that is in &lt;em&gt;limited
supply&lt;/em&gt;. Such a loop leads inevitably to &lt;em&gt;concentration&lt;/em&gt; of
said resource.&lt;/p&gt;
&lt;p&gt;If we consider &lt;em&gt;education&lt;/em&gt; to be a profit-center&lt;a href=&quot;https://xn--izc.com/posts/have-loop/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; as
is the case in the United States, then education becomes part of a
have-loop across generations. In other words, the passage of time will
concetrate education on a shrinking educated class.&lt;/p&gt;
&lt;p&gt;One example of this is wealth – because wealth begets wealth.
Inevitably this leads to concentration of wealth to an increasingly
smaller group of people&lt;a href=&quot;https://xn--izc.com/posts/have-loop/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;. There is no natural equilibrium
state absent external regulation.&lt;/p&gt;
&lt;p&gt;Have-loops are inherently unsustainable. Have-loops inherently lead
to concentration of resources.&lt;/p&gt;
&lt;p&gt;Wherever society allows a have-loop to exist, inequality will
inevitably grow.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;The terms “cost-center” and “profit-center” typically
refer to businesses. But they can also apply to societal policy where as
a society we decide that certain things should be done for profit while
certain other things should be available to everyone.&lt;a href=&quot;https://xn--izc.com/posts/have-loop/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;People tend to focus on income inequality, which is an
important factor. But another factor that drives extreme wealth
concentration is hyper-extraction. Much like extraction of natural
resources, hyper-extraction can also be directed towards individuals and
entire demographies. Measures of income equality will eventually fall
against another’s ability to enact hyper-extraction.&lt;a href=&quot;https://xn--izc.com/posts/have-loop/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>When Your Feature Gets Someone Hurt</title>
      <link href="https://xn--izc.com/posts/when-your-feature-gets-someone-hurt/" />
      <updated>2024-05-22T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/when-your-feature-gets-someone-hurt/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/when-your-feature-gets-someone-hurt/album-of-ruins.jpg&quot; class=&quot;noinvert&quot; alt=&quot;An old photo album containing pictures of ruins. (Generated with Gemini)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;An old photo album containing pictures of
ruins. (Generated with Gemini)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A story making the rounds recently opened some disturbing
implications. The New York Times ran the story as &lt;a href=&quot;https://www.nytimes.com/2024/03/27/technology/israel-facial-recognition-gaza.html&quot;&gt;Israel
Deploys Expansive Facial Recognition Program in Gaza&lt;/a&gt; which says in
part:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To supplement Corsight’s technology, Israeli officers used Google
Photos, the free photo sharing and storage service from Google, three
intelligence officers said. By uploading a database of known persons to
Google Photos, Israeli officers could use the service’s photo search
function to identify people.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Whether this particular use of Google Photos is compliant with the
usage policy is irrelevant. Those are concerns for PR firms and lawyers.
Google Photos is a consumer product. People use it for tagging their
family and friends in their vacation photos. The product works pretty
well for this purpose.&lt;/p&gt;
&lt;p&gt;The humanity behind the product developers and those who are
unexpectedly and unwittingly blindfolded and led away to some unkonwn
prison somewhere is an entirely different matter.&lt;/p&gt;
&lt;p&gt;The intended usage of a product – especially software products –
matters greatly. People responsible for these features decide its fit
for purpose based on this intended usage. From their point of view, a
mislabelled photo is an inconvenience; possibly a funny one. The error
thresholds were never decided based on whether someone could lose their
life for it.&lt;/p&gt;
&lt;p&gt;Some developer wrote a conditional branch without giving it a second
thought. And now it decides the fate of a human life. That’s quite the
turn of events.&lt;/p&gt;
&lt;p&gt;There’s no moral here. People are going to use your products in ways
that you never intended. I bet the people who designed coins have no
idea the extents to which those coins were flipped for. And so it
goes.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Secret Life of Systems</title>
      <link href="https://xn--izc.com/posts/secret-life-of-systems/" />
      <updated>2024-03-23T21:59:29Z</updated>
      <id>https://xn--izc.com/posts/secret-life-of-systems/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Software systems aim to solve real world problems. They implement
some behavior that the authors of the system believe would address the
problem.&lt;/p&gt;
&lt;p&gt;For non-trivial systems the coupling is imperfect between the real
world problem, the problem as understood by some group of people, the
perceived solution, the solution as it is actually implemented, and the
solution as received by the users.&lt;/p&gt;
&lt;p&gt;The diagram below illustrates this phenomenon.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/secret-life-of-systems/lifecycle.png&quot; class=&quot;fullbleed&quot; alt=&quot;Software systems lifecycle. (Described in prose below)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Software systems lifecycle. (Described in
prose below)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The software&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; system life-cycle begins – as most
things do – in the real world.&lt;/p&gt;
&lt;h3 id=&quot;the-problem-p&quot;&gt;The Problem (P)&lt;/h3&gt;
&lt;p&gt;There is a problem that affects some group of people&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.
Let’s call it &lt;strong&gt;P&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We know these problems exist by their symptoms. For example people
might just feel something isn’t pretty great or that things could be
better if only we could figure out how.&lt;/p&gt;
&lt;p&gt;Beyond that a precise and comprehensive definition of the problem
doesn’t exist. This might seem like a strong claim, but it comes down to
the fact that everything involving people is complicated.&lt;/p&gt;
&lt;h3 id=&quot;the-model-m&quot;&gt;The Model (M)&lt;/h3&gt;
&lt;p&gt;So people set out to understand the problem deeper. Experimentation,
user studies, interviews, observations, are all things that we do to
conjure these invisible problems into existence. We go probing for
symptoms to understand what might be causing them.&lt;/p&gt;
&lt;p&gt;Based on these we develop and a model of the problem. The model may
be laid out for everone to see or it could be in someone’s head.&lt;/p&gt;
&lt;p&gt;Let’s call this &lt;strong&gt;M&lt;/strong&gt; for &lt;em&gt;model&lt;/em&gt;. The model is
the entirety of our &lt;em&gt;understanding&lt;/em&gt; of the problem. It is a
prerequisite before we can theorize about …&lt;/p&gt;
&lt;h3 id=&quot;the-solution-s&quot;&gt;The Solution (S)&lt;/h3&gt;
&lt;p&gt;At first the solutions are themselves models – things that work
&lt;em&gt;in theory&lt;/em&gt; when evaluated against the model &lt;strong&gt;M&lt;/strong&gt;,
but yet to be verified against the real world problem
&lt;strong&gt;P&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The models of solutions – let’s call them &lt;strong&gt;S&lt;/strong&gt; – are
what we think will address what we assume is the problem. Depending on
the level of rigor, we will draw little diagrams, write design
documents, shop our ideas around, discuss alternatives, collaborate and
refine these solutions.&lt;/p&gt;
&lt;p&gt;Eventually or during this process we will put something together that
works somewhat.&lt;/p&gt;
&lt;h3 id=&quot;the-implementation-i&quot;&gt;The Implementation (I)&lt;/h3&gt;
&lt;p&gt;So an implementation comes together – let’s call it
&lt;strong&gt;I&lt;/strong&gt;. The difference between &lt;strong&gt;S&lt;/strong&gt; and
&lt;strong&gt;I&lt;/strong&gt; stems from practical matters. Time, resources,
technical limitations, all affect how much of our model solution
&lt;strong&gt;S&lt;/strong&gt; we can implement. The result is often different from
what we thought we would eventually have.&lt;/p&gt;
&lt;h3 id=&quot;deployment-d&quot;&gt;Deployment (D)&lt;/h3&gt;
&lt;p&gt;Whatever solution we put together is useless unless we take our
masterpiece to those who are experiencing the problem – the users.&lt;/p&gt;
&lt;p&gt;The likelihood of a non-trivial solution reaching its entire intended
audience is low. The implementation may not be received in the same
spirit in which it was built.&lt;/p&gt;
&lt;p&gt;And often, this is the point at which we will find out how much our
solution matches the needs of the real world.&lt;/p&gt;
&lt;p&gt;They way in which our implementation &lt;strong&gt;I&lt;/strong&gt; interacts
with the real world is – the deployment &lt;strong&gt;D&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Much like the subject at hand, systems lifecycles don’t follow neatly
delineated phases as described. Real systems typically exist in all
phases simultaneously. Understanding the question is a continuous
process. Plans change all the time. As any engineer will tell you, what
tools and resources are available are &lt;em&gt;also&lt;/em&gt; part of the problem
statement.&lt;/p&gt;
&lt;p&gt;But there are a few key observations that you can make from this
model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;We lose information at every phase&lt;/strong&gt;. Our model of
the real world problem is guaranteed to be of much lower fidelity than
the real thing&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;. Our model solution is going to fall
short of addressing our model solution. Our implementation will not
match our aspirational solution. And whatever we manage to get in users
hands isn’t quite working the way we thought it would.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding the problem is a continuous
process&lt;/strong&gt;. Every phase of this lifecycle brings with it new
insights into what it is we want to achieve and what we are working
with. Each new insight changes our problem statement, solution, and
eventually implementation and deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding the problem must be deliberate&lt;/strong&gt;.
Given that the deployed solution isn’t quite a match for the real world
problem, we need to ensure that we have the right measurements and
probes in place to understand this mismatch – be it telemetry, user
satisfaction surveys, interviews, or whatever else.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whenever we are holding some concept, being conscious about where in
the lifecycle that thing fits helps us get a sense for the level of
maturity of the concept and where you need to be to solve the
problem.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;The concept applies equally to non-software systems – as
long as they aim to solve real world problems.&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;Problems that we are interested in are those that affect
people. They tend to by squishy and ill-defined. Problems that are
defined entirely in the theoretical relam don’t fall into the model that
we are going to discuss. Theoretical subproblems like that are what we
use to construct solutions for the evolving squishy problems that we are
discussing here.&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;… which is why it is called a “model”.&lt;a href=&quot;https://xn--izc.com/posts/secret-life-of-systems/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Why I Hate Carousels</title>
      <link href="https://xn--izc.com/posts/why-i-hate-carousels/" />
      <updated>2024-01-25T17:54:46Z</updated>
      <id>https://xn--izc.com/posts/why-i-hate-carousels/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;A carousel interaction pattern looks like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/dell.png&quot; class=&quot;noinvert&quot; alt=&quot;A screenshot of dell.com from Nielsen Norman Group’s article on effective design of carousels.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A screenshot of dell.com from &lt;a href=&quot;https://www.nngroup.com/articles/designing-effective-carousels/&quot;&gt;Nielsen
Norman Group’s article on effective design of
carousels&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Basically it’s a layout pattern where one starts out positioning
content in vertical blocks. Some of those blocks are going to have
content arranged in horizontal blocks.&lt;/p&gt;
&lt;p&gt;So far so good. You might think this will result in a layout that
roughly looks like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/vertical-and-horizontal-layout.png&quot; alt=&quot;A layout consisting of vertically arranged blocks. One of the blocks contains a set of horizontally arranged blocks.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A layout consisting of vertically
arranged blocks. One of the blocks contains a set of horizontally
arranged blocks.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This is a pretty common block structured layout. So common in fact
that most block structured layouts will flip orientation by nesting
level. If you nest a layout block inside a block that has vertical
layout then the inner block will automatically switch to doing
horizontal layout.&lt;/p&gt;
&lt;p&gt;Notice that the entire layout fits snugly within the viewport.&lt;/p&gt;
&lt;h3 id=&quot;layout-runneth-over&quot;&gt;Layout Runneth Over&lt;/h3&gt;
&lt;p&gt;Interesting stuff happen when the layout doesn’t fit inside the
viewport. When it doesn’t fit vertically, obviously you’ll have to
scroll up and down to see the whole thing.&lt;/p&gt;
&lt;p&gt;However, if &lt;em&gt;only the horizontal block doesn’t fit&lt;/em&gt;, that’s
when the carousel pattern kicks in. So now things start looking like
this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/layout-with-overflow.png&quot; alt=&quot;The layout no longer fits within the cofines of the viewport.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The layout no longer fits within the
cofines of the viewport.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;How do you construct a UI affordance that lets people pan around
this? Of course you use … wait I already mentioned it ..
&lt;strong&gt;pan&lt;/strong&gt;. Maybe use scroll bars or just about any other
scrolling affordance.&lt;/p&gt;
&lt;p&gt;So would it look like this if you scroll both horizontally and
vertically a little bit?&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/shifted-viewport-position.png&quot; alt=&quot;A viewport shifted a little bit both horizontally and vertically. The relative position of the blocks are still the same as before. Large portions of the viewport are now blank.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A viewport shifted a little bit both
horizontally and vertically. The relative position of the blocks are
still the same as before. Large portions of the viewport are now
blank.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;sliiiiiide-to-the-right&quot;&gt;Sliiiiiide To The Right&lt;/h3&gt;
&lt;p&gt;To address all the blankness, the carousel pattern posits that the
the overflowing horizontal bits should be moved around independently of
the vertical bits. Like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/sliding-around-horizontally.png&quot; alt=&quot;Vertically arranged bits move vertically. Horizontally arranged bits move horizontally.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Vertically arranged bits move vertically.
Horizontally arranged bits move horizontally.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We once again have the problem of affordances. There are many ways of
doing this. Most devices have some way of panning around both
horizontally and vertically. So the solution is obvious. Right?&lt;/p&gt;
&lt;p&gt;If people stop here and implement that, then that would’ve been
over.&lt;/p&gt;
&lt;h3 id=&quot;uh-oh.-here-come-the-dots-of-stupidity&quot;&gt;Uh oh. Here come the
dots of stupidity…&lt;/h3&gt;
&lt;p&gt;Instead, they went with this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/dots-of-stupidity.png&quot; alt=&quot;Dots of stupidity. Little circles and left and right arrows. When you click/tap on the left arrow button, the carousal slides to the left. When you click/tap on the right arrow button, the carousel moves to the right.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Dots of stupidity. Little circles and
left and right arrows. When you click/tap on the left arrow button, the
carousal slides to the left. When you click/tap on the right arrow
button, the carousel moves to the right.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Let me summarize this interaction pattern.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Use scroll bars, or whatever scrolling afforance to scroll up and
down to access bits that are above and below the viewport.&lt;/li&gt;
&lt;li&gt;Click/tap on little circles with arrows to access bits that are on
either side of the viewport but only within the single sliding carousel
block containing the arrows.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There’s a couple of problems with this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The obvious wonkiness of having two different methods of scrolling
horizontally and vertically.&lt;/li&gt;
&lt;li&gt;Too easy to tap on the underlying “tile” instead of the
dot-of-stupidity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Carousel sympathizers explain the reasoning for this as follows:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;What if there was more than one horizontally sliding
thingies? How would one know which horizontally sliding thingy to apply
the horizontal scroll operation to?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a purely hypothetical problem that often doesn’t exist. But I
understand that UX designers have to account for the
possibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;It’s okay because the user doesn’t always need to or want to
see everything in the carousal. Why bother them with details they don’t
need?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s nice, but how would the user know they don’t need to see the
thing without seeing the thing? It might be possible if all the visible
things in the carousel were irrelevant to the user then they’ll just
ignore the whole carousel.&lt;/p&gt;
&lt;p&gt;But what about the very users who &lt;em&gt;are&lt;/em&gt; interested? They need
to jump through hoops to look at the things that &lt;em&gt;are&lt;/em&gt;
relevant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;What if there’s sooo many things in the horizontal slidey bit
that we can’t possibly accommodate all of it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Someone has to click on the little dot with the arrow enough
times to see each one incrementally. The number of items for which such
a UI works is far smaller than a UI where one scrolls past them using a
much more ergonomic interface.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;whats-better&quot;&gt;What’s Better?&lt;/h3&gt;
&lt;p&gt;Try wrapping the horizontal blocks so the page only overflows
vertically.&lt;/p&gt;
&lt;p&gt;If there’s too many things to fit in a vertical overflow layout, then
there’s already too many things for anyone to click through individual
cards to see.&lt;/p&gt;
&lt;p&gt;Just show the user a good subsample. If it whets their appetite, then
offer them a link to take them to a dedicated page.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/why-i-hate-carousels/vertical-overflow-only.png&quot; alt=&quot;Wrap the horizontal blocks so there’s only vertical overflow.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Wrap the horizontal blocks so there’s
only vertical overflow.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;in-summary&quot;&gt;In Summary&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don’t use carousels in your UI.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instead, if you must stick content into little cards, let
the horionztal layout wrap to additional lines.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If you end up with too many horizontal lines of content,
then you definitely have too many items that can be accessed via a
horizontally panning UI. You need a different UI
altogether.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
    <entry>
      <title>Inclusion/Equity and Evaluating Negatives</title>
      <link href="https://xn--izc.com/posts/evluating-negatives/" />
      <updated>2024-01-10T02:58:34Z</updated>
      <id>https://xn--izc.com/posts/evluating-negatives/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Privacy, security, inclusion, equity, accessibility, … all of these
have an interesting property in common. When evaluation products against
such questions you are usually trying to establish a negative.&lt;/p&gt;
&lt;h3 id=&quot;to-prove-a-negative&quot;&gt;To Prove A Negative&lt;/h3&gt;
&lt;p&gt;Proving a negative requires providing &lt;a href=&quot;https://en.wikipedia.org/wiki/Evidence_of_absence&quot;&gt;evidence of
absence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If one wanted to &lt;em&gt;disprove&lt;/em&gt; the claim &lt;em&gt;“all primes are
odd”&lt;/em&gt; one only needs to prove &lt;em&gt;“some primes are even”&lt;/em&gt;. The
latter can be accomplished by finding a single counterexample – the
number 2. On the other hand if one wanted to &lt;em&gt;prove&lt;/em&gt; the claim,
they would need establish that all primes are odd. Another example is
the claim &lt;em&gt;“there are no vermin in this house,”&lt;/em&gt; proving which
requires an exahustive search of the premises. Once again, disproving
the claim only requires a single piece of evidence – a mouse.&lt;/p&gt;
&lt;p&gt;Going back to the beginning, asking someone whether a product is
&lt;em&gt;secure&lt;/em&gt;, &lt;em&gt;private&lt;/em&gt;, &lt;em&gt;inclusive&lt;/em&gt;,
&lt;em&gt;accessible&lt;/em&gt; etc… fall into the same category. Answering these
questions require proving that there is nothing &lt;em&gt;insecure&lt;/em&gt;,
&lt;em&gt;privacy violating&lt;/em&gt;, &lt;em&gt;non-inclusive&lt;/em&gt;, or
&lt;em&gt;inaccessible&lt;/em&gt; about this product. These questions are even worse
than the one about vermin from before because it’s not even clear where
to start looking. People who have spent their entire careers studying
the subject would find the criteria difficult or downright impossible to
evaluate.&lt;/p&gt;
&lt;p&gt;Despite this apparent futility, there is hope. &lt;strong&gt;Knowing that
the criteria holds under a limited set of circumstances is sometimes
enough&lt;/strong&gt;. Often it is the best that we can do.&lt;/p&gt;
&lt;h3 id=&quot;proof-by-enumeration&quot;&gt;Proof By Enumeration&lt;/h3&gt;
&lt;p&gt;In security and privacy parlance this limited scope is called the &lt;a href=&quot;https://en.wikipedia.org/wiki/Threat_model&quot;&gt;&lt;em&gt;threat
model&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Absolute security is impossible, so one would start by establishing
the specific threats that they would like to deal with. For example when
considering the security of a networked application one could start by
drawing out a &lt;a href=&quot;https://www.lucidchart.com/pages/data-flow-diagram&quot;&gt;data flow
diagram&lt;/a&gt; and then going over the different points at which data would
be at risk of being compromised. Enumeration of vulnerabilities and
threats in this way opens up the possibility of thoroughly examining the
&lt;a href=&quot;https://www.ibm.com/topics/attack-surface&quot;&gt;attack surface&lt;/a&gt;.
Thus the previously intractable problem becomes finite.&lt;/p&gt;
&lt;p&gt;As our understanding of threats improve, so does the effectiveness of
the threat model. Historically, understanding this kind of problem space
takes time and many – often costly – mistakes. The boundaries sometimes
only become known when someone exploits it.&lt;/p&gt;
&lt;p&gt;Similarly, when evaluating a squishy concept like inclusion and
equity one would also start with a well defined scope that lends itself
to examination. Just like before, often we only learn where to look for
problems the hard way. So we come up with methodologies like carefully
curated &lt;strong&gt;dimensions of identity&lt;/strong&gt;. Enumerations like that
give us a finite set of things to consider with our finite resources.
Additionally these methodologies also grant us a taxonomy with which we
can organize our hard earned knowledge on the topic.&lt;/p&gt;
&lt;h3 id=&quot;proof-by-enumerating-product-outcomes&quot;&gt;Proof by Enumerating
Product Outcomes&lt;/h3&gt;
&lt;p&gt;Enumeration based approaches establish clusters of &lt;em&gt;possible
product outcomes&lt;/em&gt; which we can then evaluate individually.&lt;/p&gt;
&lt;p&gt;As an example, a product that processes pictures of people can be
evaluated based on the outcome of handling pictures of people with
different skin tokes, gender expressions, body types, ages, hair and
accesories, visible disabilities, and lighting conditions. Coming up
with these outcomes can be laborious and expensive, but it is tractable.
Costs of curating suitably detailed test cases and data sets should
amortize across their potentially broad applicability.&lt;/p&gt;
&lt;h3 id=&quot;proof-by-construction&quot;&gt;Proof By Construction&lt;/h3&gt;
&lt;p&gt;But sometimes the set of outcomes do not cluster effectively or are
too numerous to exhaustively evaluate. In security this would be similar
to asking whether some software system is free from &lt;a href=&quot;https://en.wikipedia.org/wiki/Buffer_overflow&quot;&gt;buffer overruns&lt;/a&gt;
– a question that is theoretically impossible to answer in general if
the method of construction is not amenable to analysis. The best we
could do is for suitably skilled persons to go through the code with a
fine toothed comb looking for potential problems; a task that is both
impractical as it is prone to error.&lt;/p&gt;
&lt;h3 id=&quot;proof-by-process-of-construction&quot;&gt;Proof by Process of
Construction&lt;/h3&gt;
&lt;p&gt;Instead we could try using programming languages that provide certain
safety guarantees: &lt;a href=&quot;https://spectrum.ieee.org/memory-safe-programming-languages&quot;&gt;memory-safe
languages&lt;/a&gt;. These safety guarantees establish the memory safety of
the resulting behavior as a consequence of the method by which the
underlying software is constructed. Another method we can use is to
continue using an unsafe language&lt;a href=&quot;https://xn--izc.com/posts/evluating-negatives/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;, but invest in
development practices like &lt;a href=&quot;https://en.wikipedia.org/wiki/Fuzzing&quot;&gt;fuzz testing&lt;/a&gt; which give
us sufficient &lt;a href=&quot;https://www.georgefairbanks.com/ieee-software-v37-n3-may-2020-testing-numbs-us-to-our-loss-of-intellectual-control&quot;&gt;statistical
control&lt;/a&gt; over the behavior of our software.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Inclusion and equity&lt;/em&gt; can follow a similar paradigm where we
establish certain process requirements that also yield a favorable
outcome with a high likelihood. Google’s &lt;a href=&quot;https://design.google/library/building-for-everyone&quot;&gt;Building for
Everyone&lt;/a&gt; outlines some of these processes criteria such as involving
a diverse group of people during the ideation and design phases of a
product, and involving a diverse group of people during testing. Once
again, these approaches don’t guarantee success, but have a much higher
likelihood of delivering a favorable outcome.&lt;/p&gt;
&lt;h3 id=&quot;amalgam-engineering&quot;&gt;Amalgam Engineering&lt;/h3&gt;
&lt;p&gt;Increasingly software systems are built as amalgamations of systems
that are themselves complex. The behavior of each constituent is
difficult to reason about let alone the behavior of the
amalgamation.&lt;/p&gt;
&lt;p&gt;To establish some desirable property of the amalgamation, it becomes
necessary to progressively establish the same or minor properties of the
constituents. &lt;strong&gt;The point of establishing these properties is to
yield a simpler more tractable model of a system&lt;/strong&gt; that we can
readily reason about. We can then infer or at least approximate the
behavior of the amalgamation based on the simplified models that we
derive of the contituents.&lt;/p&gt;
&lt;p&gt;We don’t expect this situation to get better given that many of these
contituent parts will be ML models that are too complex for us to
understand. As enumerating product outcomes becomes less effective, we
will need to rely ever more on process criteria and governance of
construction to curb the product outcomes.&lt;/p&gt;
&lt;p&gt;The accuracy of the resulting simplified models is all that we will
have to grasp in order to have some say how technology will govern us in
turn.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Continuing to use an unsafe language isn’t as dumb as it
sounds. Large tech companies with massive software estates are often in
the unenviable position of being unable to move enmasse to better
platforms due to the cost. Thus less than perfect interim measures are
not that silly.&lt;a href=&quot;https://xn--izc.com/posts/evluating-negatives/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Happy New Year 2024 and Year in Review 2023</title>
      <link href="https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/" />
      <updated>2024-01-01T19:12:21Z</updated>
      <id>https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/</id>
      <content xml:lang="en" type="html">
        &lt;h2 id=&quot;happy-new-year-everyone&quot;&gt;Happy New Year Everyone!&lt;/h2&gt;
&lt;p&gt;I hope everyone has a great year in 2024!&lt;/p&gt;
&lt;h2 id=&quot;what-we-are-leaving-behind&quot;&gt;What We Are Leaving Behind&lt;/h2&gt;
&lt;p&gt;I’m acknowledging but not going into details of the cruelty we are
inflicting on ourselves in Ukrain, the Gaza strip, Myanmar, Niger,
Burkina Faso, Azawad, Tunisia, Sudan, Columbia, Afganistan, Pakistan,
Somalia, Democratic Republic of Congo, Nigeria, Iraq, Rwanda, Burundi,
Mexico, Camaroon, Chad, Syria, Yemen, Saudi Arabia, United Arab
Emirates, Ethiopia, Haiti, and pretty much everwhere.&lt;/p&gt;
&lt;p&gt;Instead let’s skip over to the the weirdness that happened in the
tech sector.&lt;/p&gt;
&lt;h2 id=&quot;generative-ai-has-entered-the-chat&quot;&gt;Generative AI Has Entered
The Chat&lt;/h2&gt;
&lt;p&gt;Educated people often make the mistake of underestimating the
disruption that can happen in an industry. In this case, we are talking
about generative AI and its disruption of the tech sector.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Transformer_%28machine_learning_model%29&quot;&gt;Transformer
models&lt;/a&gt; have been around for a while (since before 2017) but they
have mostly been a curiousity rather than a serious practical tool. It
held much promise and excitement but was considered to be a technology
that was in its infancy. The only real production workloads they handled
were around machine translation.&lt;/p&gt;
&lt;p&gt;However, a sudden disruption happened in 2023 where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI models become capable enough to give a somewhat convincing
approximation of intelligence. This led people to conclude that
generative AI is now ready for use in industry – a claim that is
debateable.&lt;/li&gt;
&lt;li&gt;Generative AI models became accessible to the general public largely
in the form of ChatGPT though others followed quickly.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;People started incorporating generative AI into their lives and
businesses.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn4&quot; class=&quot;footnote-ref&quot; id=&quot;fnref4&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;This triggered an influx of financial investment in generative AI.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn5&quot; class=&quot;footnote-ref&quot; id=&quot;fnref5&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn6&quot; class=&quot;footnote-ref&quot; id=&quot;fnref6&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Which was followed closely by legislation that aimed to mitigate the
perceived harm of AI.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fn7&quot; class=&quot;footnote-ref&quot; id=&quot;fnref7&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;7&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this in the span of a year.&lt;/p&gt;
&lt;p&gt;I’m not directly involved in any ML work, so the way I experienced it
was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At the start of the year I had a couple of &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;NLP&lt;/a&gt;
projects that I had lined up to complete by the end of the year. The
tasks were somewhat complex and involved fiddling with a lot of
NLP.&lt;/li&gt;
&lt;li&gt;By the end of the year the tasks were reduced to producing a prompt
for an LLM and then parsing its result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to all the assistive coding tasks that are pretty much
production ready at this point, the transformation of a complex coding
task into simple English question and answer is kind of mind
blowing.&lt;/p&gt;
&lt;p&gt;I’m waiting to see what the new year is going to bring in terms of
automation. We are truly living in the future.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.salesforce.com/news/stories/generative-ai-statistics/#:~:text=45%25%20of%20the%20US%20population%20surveyed%20is%20using%20generative%20AI.&quot;&gt;“45%
of US population surveyed is using generative AI”&lt;/a&gt; according to
Salesforce.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;See McKinsey’s &lt;a href=&quot;https://www.mckinsey.com/capabilities/quantumblack/our-insights/the-state-of-ai-in-2023-generative-ais-breakout-year&quot;&gt;the
state of AI in 2023: Generative AI’s breakout year&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://twitter.com/gdb/status/1599683104142430208&quot;&gt;“ChatGPT just
crossed 1 million users; it’s been 5 days since launch.”&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn4&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://advisory-marketing.us.kpmg.com/speed/genai2023.html#:~:text=Three%20in%20four%20business%20leaders%20%2874%25%29%20rank%20generative%20AI%20as%20the%20top%20emerging%20technology%20that%20will%20impact%20their%20business%20over%20the%20next%20year%20and%20a%20half.&quot;&gt;“Three
in four business leaders (74%) rank generative AI as the top emerging
technology that will impact their business over the next year and a
half.”&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref4&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn5&quot;&gt;&lt;p&gt;Funding for AI-related startups were more than $65
billion in 2023. See TechCrunch’s &lt;a href=&quot;https://techcrunch.com/2023/12/05/mega-deals-ai-funding-q3/#:~:text=Funding%20for%20AI%2Drelated%20startups,substantial%20portion%20of%20that%20figure.&quot;&gt;‘Mega-deals’
could be inflating overall AI funding figures&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref5&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn6&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.bloomberg.com/company/press/generative-ai-to-become-a-1-3-trillion-market-by-2032-research-finds/&quot;&gt;“Generative
AI to Become $1.3 Trillion Market by 2023, Research Finds”&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref6&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn7&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.ncsl.org/technology-and-communication/artificial-intelligence-2023-legislation#:~:text=In%20the%202023%20legislative%20session%2C%20at%20least%2025%20states%2C%20Puerto%20Rico%20and%20the%20District%20of%20Columbia%20introduced%20artificial%20intelligence%20bills%2C%20and%2015%20states%20and%20Puerto%20Rico%20adopted%20resolutions%20or%20enacted%20legislation.&quot;&gt;“In
the 2023 legislative session, at least 25 states, Puerto Rico and the
District of Columbia introduced artificial intelligence bills, and 15
states and Puerto Rico adopted resolutions or enacted
legislation.”&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/happy-new-year-2024-and-year-in-review-2023/#fnref7&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Thirteen Years</title>
      <link href="https://xn--izc.com/posts/thirteen-years/" />
      <updated>2023-12-07T21:30:52Z</updated>
      <id>https://xn--izc.com/posts/thirteen-years/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;And just like that, another year sped by. It’s now been thirteen
years since I joined Google.&lt;/p&gt;
&lt;p&gt;Of the people who started at Google that day just a hair over 50% are
still at Google. Glancing through the list&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; I
see a couple of folks who have left for greener pastures or pursuing
something on their own. Others who are still here have made their way up
the organizational ladders.&lt;/p&gt;
&lt;p&gt;But for everyone on that list the Google of today is not the Google
we joined all those years ago. Someone who had been at Google much
longer than I have &lt;a href=&quot;https://ln.hixie.ch/?start=1700627373&amp;amp;count=1&quot; title=&quot;Ian Hixie&amp;#39;s blog: Reflecting on 18 years at Google&quot;&gt;recently
published their thoughts&lt;/a&gt; after they left Google. They had good
things to say about Google, but they also had some pretty harsh things
to say. I can’t comment about some of the specifics they mentioned but
the general sentiment checks out.&lt;/p&gt;
&lt;p&gt;Avery Pennarun&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; wrote a post that I think touches on
something relevant and important. The post is called &lt;a href=&quot;https://apenwarr.ca/log/20190926&quot; title=&quot;What do executives do anyway?&quot;&gt;What do executives do anyway?&lt;/a&gt;.
To save you a read (though you really should add it to your &lt;a href=&quot;https://support.google.com/chrome/answer/7343019?hl=en&quot; title=&quot;Read pages later &amp;amp; offline&quot;&gt;reading list&lt;/a&gt;), the salient
points are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An executive’s &lt;strong&gt;&lt;em&gt;only&lt;/em&gt;&lt;/strong&gt; job is to &lt;em&gt;“enforce
&lt;strong&gt;culture and values&lt;/strong&gt; for their whole
organization.”&lt;/em&gt;&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The executives set and enforce the values. The rest of the company
comes up with strategies accordingly.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“In a large organization, executives don’t set strategy.”&lt;/em&gt; …
&lt;em&gt;“It’s an illusion to believe you can enforce a strategy.”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Useful organizational values involve real tradeoffs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;People have a common misconception that all employees of big
companies are constantly thinking of the bottom line. This is not the
case. Precious few teams can draw a clear line from their day-to-day
work to any measurable change in the company’s performance&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fn4&quot; class=&quot;footnote-ref&quot; id=&quot;fnref4&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;. So
at an individual level, decisions are influenced by concerns much closer
to themselves: things like base pay, career, admiration of their peers,
and their own sense of accomplishment.&lt;/p&gt;
&lt;p&gt;There are many things that an individual can work on to satisfy their
immediate concerns. The &lt;em&gt;culture and values&lt;/em&gt; of a company help
narrow these options down to those that benefit everyone.&lt;/p&gt;
&lt;p&gt;The reason I brought up the topic of culture and values is because
Google has a vacuum where an inspiring vision once was. Layoffs wreaked
havoc with the trust that people had for each other and themselves. We
are still &lt;em&gt;trying&lt;/em&gt; to &lt;a href=&quot;https://about.google/philosophy/&quot; title=&quot;Ten things we know to be true&quot;&gt;focus on the user&lt;/a&gt;; &lt;a href=&quot;https://blog.google/inside-google/message-ceo/january-update/#:~:text=important%20moments%20to-,sharpen%20our%20focus,-%2C%20reengineer%20our%20cost&quot; title=&quot;A difficult decision to set us up for the future&quot;&gt;sharply, in
fact&lt;/a&gt;. But it is evident that company and its people are increasingly
acting out of self preservation,&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;There’s a mailing list for the folks who started on the
same day.&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;Avery is also a Xoogler.&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;The article goes into detail about ratifying good
decisions and arbitrating difficult decisions. But those are not
relevant to this discussion.&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn4&quot;&gt;&lt;p&gt;You can, however, affect the stock price by getting
something really really wrong. Noone wants to be in this position
though.&lt;a href=&quot;https://xn--izc.com/posts/thirteen-years/#fnref4&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Pillars And Governance Structures</title>
      <link href="https://xn--izc.com/posts/pillars-are-governance-structures/" />
      <updated>2023-09-09T00:18:23Z</updated>
      <id>https://xn--izc.com/posts/pillars-are-governance-structures/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Note: Originally published on 2023 September 8. Revised 2023 November
12 with hopefully less rambling.&lt;/p&gt;
&lt;p&gt;Re-orgs.&lt;/p&gt;
&lt;p&gt;It’s a fact of life for large organizations. A popular metaphor
making the rounds now is this concept of pillars. The metaphor makes
sense to some extent.&lt;/p&gt;
&lt;h2 id=&quot;a-house-without-a-foundation&quot;&gt;A house without a foundation&lt;/h2&gt;
&lt;p&gt;Let’s start with a picture of how a sanitized version of a pillar
structure would look like.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/just-pillars-and-a-goal.png&quot; alt=&quot;A goal at the top and a bunch of pillars at the bottom. No foundation.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A goal at the top and a bunch of pillars
at the bottom. No foundation.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On the top is some kind of goal or an organization. In the case of an
organization we can think of organization’s mission as the goal. Pillars
support the goal.&lt;/p&gt;
&lt;h2 id=&quot;stage-2-subpillars&quot;&gt;Stage 2: Subpillars&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/pillars-and-subpillars.png&quot; alt=&quot;A goal at the top, a bunch of pillars holding it up, and then a bunch of subpillars. Still no foundation.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A goal at the top, a bunch of pillars
holding it up, and then a bunch of subpillars. Still no
foundation.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Massive corporations can’t be organized around a handful of pillars.
We need more structure: subpillars.&lt;/p&gt;
&lt;p&gt;The subpillars are holding up the pillars. Together all of them hold
up the goal.&lt;/p&gt;
&lt;p&gt;Collectively what we are looking at is a system for organizing
people. One that is hierarchical and tree structured.&lt;/p&gt;
&lt;p&gt;We all know this. Because that’s what org charts have always looked
like.&lt;/p&gt;
&lt;h2 id=&quot;team-topologies&quot;&gt;Team Topologies&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://martinfowler.com/bliki/TeamTopologies.html&quot;&gt;TeamTopologies&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Martin Fowler et. al. discusses
different kinds of software teams.&lt;/p&gt;
&lt;p&gt;One can think of pillars and sub-pillars as being higher level
structures for organizing these teams. Individual teams at the
granularity at which team topologies apply are too granular for
pillars.&lt;/p&gt;
&lt;p&gt;What I found compelling in “Team Topologies” were the concepts of
&lt;strong&gt;Outcome Oriented teams&lt;/strong&gt; and &lt;strong&gt;Activity Oriented
teams&lt;/strong&gt;. These have always had names – &lt;strong&gt;project
teams&lt;/strong&gt; and &lt;strong&gt;service teams&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Fowler’s article mentions&lt;/p&gt;
&lt;p&gt;To put it in a nutshell,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Outcome oriented teams&lt;/strong&gt; are teams that are
working towards something. They hope to achieve some sort of goal, and
once it is achieved the purpose of the team has been fulfilled and
typically people move on to other things.&lt;/p&gt;
&lt;p&gt;Outcome oriented teams have specific measurable goals like…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;build a thing,&lt;/li&gt;
&lt;li&gt;make specific qualitative change happen,&lt;/li&gt;
&lt;li&gt;research something, or&lt;/li&gt;
&lt;li&gt;achieve a sales goal.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Activity oriented teams&lt;/strong&gt; are teams that perform
some sort of activity for the organization. They do things like keeping
the lights on, bug fixing, and occasional feature development. Activity
oriented teams are typically in the service of enabling an outcome.&lt;/p&gt;
&lt;p&gt;Activity oriented teams have qualitative goals like&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;uptime,&lt;/li&gt;
&lt;li&gt;efficiency,&lt;/li&gt;
&lt;li&gt;user-satisfaction, and&lt;/li&gt;
&lt;li&gt;level of support.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are more details and nuances and much hair-splitting. But the
gist of it can be understood without diving too far into the weeds. What
is important is that …&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Outcome oriented teams and activity oriented teams can mutually
depend on each other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also …&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A single outcome oriented team can depend on multime activity
oriented teams.&lt;/p&gt;
&lt;p&gt;For example, a team tasked with building a new service will depend on
multiple existing services that are under the purview of multiple
activity oriented teams.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A single activity oriented team can depend on multiple outcome
oriented teams.&lt;/p&gt;
&lt;p&gt;For example, a team tasked with maintaining a critical service will
at times need to implement large changes or features, which require
multiple outcome oriented teams.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Uh oh. Our organization is not tree-shaped anymore.&lt;/p&gt;
&lt;h2 id=&quot;its-a-graph&quot;&gt;It’s a Graph&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/graph-shaped-dependencies.png&quot; alt=&quot;Interdependencies form a graph, not a tree.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Interdependencies form a graph, not a
tree.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The problem is that the the thing we are trying to organize is not
tree structured. Each group has relationships that stretch vertically
along the reporting chain, and also horizontally across “enabling”
teams, support teams, infrastructure teams, or other teams that are
solving similar problems.&lt;/p&gt;
&lt;p&gt;An organization especially at this level of abstraction cannot
represent all this complexity. A large number of free-floating small
teams interacting with each other won’t be very efficient&lt;a href=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.
Nor is it conducive to goals at a large scale because that would require
a degree of cooperation that won’t appear spontaneously.&lt;/p&gt;
&lt;p&gt;So we need to steer this pool of teams. It needs some structure so
that some higher level of management can coordinate a number of smaller
groups; so that they can collectively work towards a common but larger
goal.&lt;/p&gt;
&lt;p&gt;With this newfound knowledge we can once again approach the pillars
but this time with goals and activities for the higher level teams.&lt;/p&gt;
&lt;h2 id=&quot;its-a-tree-again&quot;&gt;It’s a Tree (Again)&lt;/h2&gt;
&lt;p&gt;However, the leadership needs to figure out which of these
relationships to organize around.&lt;/p&gt;
&lt;p&gt;This isn’t quite satisfactory yet because we can’t made things fit
into the pillar system. Once people get stuck on pillars everything
needs to be a pillar.&lt;/p&gt;
&lt;p&gt;We can, however, stick teams into pillars. These teams would be
outcome oriented if they are stuck into outcome oriented pillars. It
follows that activity oriented pillars will need to be stuck into
activity oriented pillars.&lt;/p&gt;
&lt;p&gt;So it’ll kind of look like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/all-together-now.png&quot; alt=&quot;Big organization, goals, outcome oriented pillars, outcome oriented teams, activity oriented pillars, and activity oriented teams&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Big organization, goals, outcome oriented
pillars, outcome oriented teams, activity oriented pillars, and activity
oriented teams&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And there you have it.&lt;/p&gt;
&lt;p&gt;In reality, the structure can be made much cleaner once you start
asking each team what their goals are.&lt;/p&gt;
&lt;p&gt;But the gist of it is you can’t plan teams or pillars until you know
what their goals are.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;I don’t believe the concepts introduced in &lt;a href=&quot;https://teamtopologies.com/&quot;&gt;Team Topologies&lt;/a&gt; don’t apply
universally even across software companies. I work in one where it
doesn’t.&lt;a href=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;Even though in the aggregate, you can think of the open
economy as being a very large number of small “teams” with a very dense
network of interdependencies. Sure, it’s leaving people in poverty and
is killing the planet; but it still kind of works.&lt;a href=&quot;https://xn--izc.com/posts/pillars-are-governance-structures/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>A Good API: g9</title>
      <link href="https://xn--izc.com/posts/a-good-api/" />
      <updated>2023-08-12T23:29:31Z</updated>
      <id>https://xn--izc.com/posts/a-good-api/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Once in a while, an API comes around that makes me stop and look at
what I’m doing.&lt;/p&gt;
&lt;p&gt;Like many aspects of design, when it comes to APIs, what is not there
matters as much as what is. Engineers like to fiddle around with things.
So they like to add knobs and dials for fiddling around with things.&lt;/p&gt;
&lt;p&gt;People say platitudes like good API design has to do with balancing
flexibility and simplicity. People throw around the word “simplicity” as
if people just need to be reminded of it and all will be well. “Simplify
your API” isn’t the same as “put on sunscreen.” It takes work. Lots of
work. Intentional work with the goal of simplifying because there is
little chance you are going to arrive at the right solution by
accident.&lt;/p&gt;
&lt;p&gt;An example of a good API is &lt;a href=&quot;https://github.com/bijection/g9&quot;&gt;g9&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before you look at it, think about how you would construct an API
that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;… allows you to draw a diagram on an HTML canvas – perhaps with a
limited set of drawing primitives.&lt;/li&gt;
&lt;li&gt;… once the diagram is rendered, allows users to manipulate the
diagram by dragging points around.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are millions of ways of designing this. But g9’s approach takes
the cake. You can take a shortcut and have a look at their &lt;a href=&quot;https://github.com/bijection/g9#docs&quot;&gt;API documentation&lt;/a&gt; or
their &lt;a href=&quot;https://omrelli.ug/g9/gallery/&quot;&gt;examples&lt;/a&gt;. But
basically, it is this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Tell us what your mutable parameters are.&lt;/li&gt;
&lt;li&gt;Draw your diagram based on the set of parameters.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. That’s all there is.&lt;/p&gt;
&lt;p&gt;Now, you can sit there and come up with a million knobs that you
claim make the API more powerful. And you might be right – you’ll be
able to do more things with the API with the knobs you add.&lt;/p&gt;
&lt;p&gt;But when you start treating simplicity as a feature, you’ll notice
that adding knobs isn’t the same as making a more powerful API. All
those additional knobs must be essentially invisible for people who
don’t need them. Otherwise, every additional knob will waste more of
your users’ time and energy for nothing.&lt;/p&gt;
&lt;p&gt;The power of an API comes from letting users express more with
less.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>The Point of a Strategy</title>
      <link href="https://xn--izc.com/posts/the-point-of-a-strategy/" />
      <updated>2023-07-24T15:00:12Z</updated>
      <id>https://xn--izc.com/posts/the-point-of-a-strategy/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;&lt;strong&gt;Q&lt;/strong&gt;: How do you win a soccer match?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: Score more goals than the other team.&lt;/p&gt;
&lt;p&gt;This is a dumb strategy, right? But why?&lt;/p&gt;
&lt;p&gt;Compared to a more &lt;em&gt;reasonable&lt;/em&gt; strategy like start preparing
with plenty of time to spare, invest in a good team, hire a good coach
and what not, &lt;em&gt;why&lt;/em&gt; is scoring more goals a dumb strategy? That’s
because the bad strategy didn’t &lt;strong&gt;reduce risk&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The whole point of a strategy is to mitigate risk. One could imagine
gathering up a bunch of random people and somehow lucking out at the
game and winning it. You need a strategy if you don’t want to leave
everything to chance.&lt;/p&gt;
&lt;p&gt;That’s why the next strategy you write down needs to account for
these:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;State your goal clearly.&lt;/p&gt;
&lt;p&gt;A good goal should clearly articulate &lt;strong&gt;the outcome&lt;/strong&gt;,
and &lt;strong&gt;constraints&lt;/strong&gt;. E.g. MVP available for limited testing
(&lt;em&gt;the outcome&lt;/em&gt;) by end of Q4 (&lt;em&gt;the constraint&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;It should be obvious to anyone when the goal has been reached. This
is by design, since there should not be any question of what you are
collectively trying to accomplish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identify the risks.&lt;/p&gt;
&lt;p&gt;Mitigating risks begin by identifying them. Some risks are obvouls,
but still write them down because you need to address them.&lt;/p&gt;
&lt;p&gt;Failing to meet the goal is an obvious risk, but why would you fail
to meet the goal?&lt;/p&gt;
&lt;p&gt;A common reasons is simply that you need more time. E.g. you are at
risk of not meeting the constraints due to underestimating the amount of
work required.&lt;/p&gt;
&lt;p&gt;Another reason could be technology you are using not performing as
expected due to bugs. Every part of your tech stack is a gamble. A part
that you don’t own is a specially big risk because you may not be able
to fix it or work around a problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Figure out how to mitigate the risks.&lt;/p&gt;
&lt;p&gt;At risk of schedules slipping? Have intermediate deliverables and
milestones along the way. Instead of everything falling apart at the
end, you’ll know when things are not going to schedule much earlier in
the product life cycle. Knowing early means that you can address them
before failures snowball into a giant ball of trouble.&lt;/p&gt;
&lt;p&gt;Unreliable tech-stack? Choose stacks that have a solid user base and
support structure. A project with bugs that are getting addressed is a
lower risk than one that hasn’t seen any updates in a year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stack up your goal, risks, and mitigations.&lt;/p&gt;
&lt;p&gt;There’s your strategy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s not a strategy is risks are not identified and mitigated.&lt;/p&gt;
&lt;p&gt;A common mistake is to write down a list of steps that, if followed,
achieve a stated goal. A good first step. But the unless the strategy
can &lt;strong&gt;reduce&lt;/strong&gt; risk, it is not a useful.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Just Enough Technical Debt</title>
      <link href="https://xn--izc.com/posts/just-the-right-amount/" />
      <updated>2023-07-08T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/just-the-right-amount/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Zero technical debt sounds like a great target to aim for. In my
earlier developer days I strongly believed that all projects should go
for this target. At a company all-hands I heard from a senior engineer
that having zero technical debt is often not what we want. I felt
betrayed.&lt;/p&gt;
&lt;p&gt;Why is it that zero technical debt isn’t what we want?&lt;/p&gt;
&lt;h2 id=&quot;memory-allocation-strategy-leak-all-allocations&quot;&gt;Memory
Allocation Strategy: Leak All Allocations&lt;/h2&gt;
&lt;p&gt;Let’s take a moment and think of a hypothetical program. If you knew
that your program ran once and terminated, would you go through the
effort of deallocating each individual memory allocation at the end? You
are about to end the process and drop the entire heap anyway. Cleaning
the heap at this point is a waste. For short-lived programs who’s memory
consumption is bounded and less than the available memory the more
efficient strategy is to just leak all memory.&lt;/p&gt;
&lt;p&gt;One might wonder if such a strategy would break reusability. “Leak
all allocations” doesn’t mean that you shouldn’t call
&lt;code&gt;free()&lt;/code&gt; (or equivalent) in your code. It means that the
memory manager would treat &lt;code&gt;free()&lt;/code&gt; as a no-op. This
principal also applies to garbage collected languages. After all, the &lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203#:~:text=Garbage%20collection%20is%20simulating%20a%20computer%20with%20an%20infinite%20amount%20of%20memory.&quot;&gt;&lt;em&gt;job
of memory management is to simulate infinite memory&lt;/em&gt;&lt;/a&gt;. If you are
only going to use a finite amount of memory then you don’t need memory
management.&lt;/p&gt;
&lt;h2 id=&quot;what-does-just-enough-technical-debt-look-like&quot;&gt;What Does Just
Enough Technical Debt Look Like?&lt;/h2&gt;
&lt;p&gt;Some of the motivation for stopping short of perfect comes from the
&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Mythical_Man-Month&quot;&gt;Mythical
Man Month&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;For the human makers of things, the incompletenesses and
inconsistencies of our ideas become clear only during implementation.
Thus it is that writing, experimentation, “working out” are essential
disciplines for the theoretician.&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;― Frederick P. Brooks Jr., The Mythical Man-Month: Essays on Software
Engineering&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;p&gt;The hardest part of the software task is arriving at a complete and
consistent specification, and much of the essence of building a program
is in fact the debugging of the specification.&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;― Frederick P. Brooks Jr., The Mythical Man-Month: Essays on Software
Engineering&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Software projects tend to be characteristically similar. Putting too
much effort into a project features you don’t need and polishing up code
that nobody will reuse is wasteful. It’s just a little bit harder to
know when you’ve crossed the point of diminishing returns where cleaning
up the code no longer makes sense.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Code As UI: The UX of config-as-code and everything-as-code</title>
      <link href="https://xn--izc.com/posts/code-as-ui/" />
      <updated>2023-07-01T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/code-as-ui/</id>
      <content xml:lang="en" type="html">
        &lt;h2 id=&quot;welcome-to-the-ui-review&quot;&gt;Welcome to the UI review&lt;/h2&gt;
&lt;p&gt;Your UX person comes up to you with the new mocks for the
configuration UI. It looks like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/code-as-ui/blank-ui.png&quot; alt=&quot;A UI mock where all the labels are text boxes, and the values are also text boxes. The button just “button”.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A UI mock where all the labels are text
boxes, and the values are also text boxes. The button just
“button”.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: What is this? Is this modern?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: That’s be beauty of it. The user can type in the
label &lt;em&gt;and&lt;/em&gt; type in the value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: And how would they know what the labels are and
what valid values are?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: We will write some documentation on what the
labels and values should be.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: What about validation?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: Hmm. That would be nice. But the UI doesn’t
really know what the valid values are.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: Come again?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: The UI is neutral. Again, the valid labels and
values are documented.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: Is it a good document?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: Let’s not get ahead of ourselves.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: Is it a single document?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: We are thinking more along the line of leaning
into crowd sourcing. Like there will be some documentation, but really
the labels and values are consumed by the backend. We don’t really have
much control of that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: So, the backend is responsible for keeping the
documentation up to date? How has that worked out before?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: Not great.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: So, any good news here? Why are we doing
this?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UX&lt;/strong&gt;: Because it’s config-as-code. It’s the new
hotness.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt;: Say no more fam.&lt;/p&gt;
&lt;p&gt;So here’s the thing. Config-as-code isn’t new. That’s how it was
before any GUIs existed. Anyone hows configured an old OS, and some new
ones, will tell you that the only way some parts can be configured is by
editing text files; sometimes using an esoteric editor called
&lt;code&gt;vi&lt;/code&gt;&lt;a href=&quot;https://xn--izc.com/posts/code-as-ui/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then there was a glorious age of GUIs. At some point they started
treating developers and sysadmins like real people. You might not
believe this, but they even did user experience testing to make sure
those sysadmins’ lives were as easy as possible. It was glorious.&lt;/p&gt;
&lt;p&gt;And now, what’s old is new again.&lt;/p&gt;
&lt;h2 id=&quot;the-pros&quot;&gt;The Pros&lt;/h2&gt;
&lt;p&gt;There are in fact good reasons for config-as-code. Here’s a few:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No more opaque configuration&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Fancy UIs often mean that the configuration data goes straight into
an opaque configuration store somewhere. Sure it will come around and
affect the behavior of whatever it was that is being configured. But
that stuff usually doesn’t involve the user.&lt;/p&gt;
&lt;p&gt;Usually the the platform doesn’t have much reason to keep
configuration a secret. So there will be some schema and some method to
storing and querying the configuration.&lt;/p&gt;
&lt;p&gt;However when it comes to third-party or hosted services, this is not
always the case. The how the configuration is stored and how it is
reified into behavior is opaque.&lt;/p&gt;
&lt;p&gt;With configuration-as-code (Can I call this CaC? That’ll be more
convenient.) the user is in control of storage. How else would they
write it down? The schema must necessarily also be made available to the
user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;All the controls of source code&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Anyone who’s written some source code and used some source control
tool will tell you how useful source control can be.&lt;/p&gt;
&lt;p&gt;Almost trivially you get:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;History&lt;/strong&gt; and all that comes with it like the
ability to revert back to known good states.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Blame/Praise&lt;/strong&gt; and attribution of changes to
specific authors – assuming there’s sufficient authentication and
authorization in place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reviews/Approvals&lt;/strong&gt; that verify that the changes
were correct and appropriate.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unless someone can be mandated to stand behind you and look over your
shoulder taking notes, none of that comes for free with a sysadmin at a
GUI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audits, validation, automation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Follows from the above. Now that the configuration is inspectable and
understandable, it is easily amenable to automation and validation.&lt;/p&gt;
&lt;p&gt;One could argue that this was always the case. However, now the user
is empowered to do so with the same fidelity as the authors of the
system.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;and-the-cons&quot;&gt;And the cons&lt;/h2&gt;
&lt;p&gt;The things that need &lt;em&gt;fixing&lt;/em&gt; is usability.&lt;/p&gt;
&lt;p&gt;We spent decades saying Fitt’s law this and “recognition over recall”
that, and then threw everything away. It’s time we put all that
experience into action.&lt;/p&gt;
&lt;p&gt;Just because the configuration is in text files doesn’t mean that it
has to be authored that way. Even if it did, it is still possible to
substantially improve the UX there.&lt;/p&gt;
&lt;p&gt;Why do people enjoy Mad Libs but wouldn’t enjoy writing the same
content from scratch? The answer is “recognition over recall”.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https://xn--izc.com/posts/code-as-ui/madlibs.png&quot; alt=&quot;The original Mad Libs book gave this example: “___________! he said ________ as he jumped into his convertible ______ and drove off with his _________ wife.” exclamation adverb noun adjective.&quot; /&gt;
 &lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;An example from the original Mad Libs book. &lt;a href=&quot;https://en.wikipedia.org/wiki/Mad_Libs&quot;&gt;Source: Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We can have the format and options documented somewhere and have the
user consult the document at every step of the way. This sound
reasonable at first. So people write things like “read all the
documentation carefully before attempting to configure the thing.”&lt;/p&gt;
&lt;p&gt;But the amount of information that a human being can keep track of at
a given time is limited. What it ends up being is a tiresom sequence of
flipping back and forth between reference and implementation.&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https://xn--izc.com/posts/code-as-ui/reference-and-configuration-eyes.png&quot; alt=&quot;Attention shifts from the reference to the configuration being edited and back; repeatedly.&quot; /&gt;
 &lt;/p&gt;
&lt;figcaption&gt;
Left to right to left to right …
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;making-things-better&quot;&gt;Making things better&lt;/h2&gt;
&lt;p&gt;It turns out we already have some ideas on how to fix this, because
the same problems plague software engineering. Or I should say the other
areas of software engineering.&lt;/p&gt;
&lt;p&gt;Here are several approaches I’ve seen in practice that make
config-as-code more bearable.&lt;/p&gt;
&lt;h3 id=&quot;language-serversautocomplete&quot;&gt;Language Servers/Autocomplete&lt;/h3&gt;
&lt;p&gt;Pretty much the only useful development in coding in the past several
decades is autocomplete. A good schema along with documentation can make
a huge difference. Try editing the VS Code settings file to see it in
action.&lt;/p&gt;
&lt;h3 id=&quot;templates&quot;&gt;Templates&lt;/h3&gt;
&lt;p&gt;As the Mad Libs example shows, templates are much easier and more
expedient than a blank empty document.&lt;/p&gt;
&lt;p&gt;Other examples of templates include:&lt;/p&gt;
&lt;p&gt;But templates in general only work the first time. So subsequent
edits to the configuration will have to contend without the help of a
template. This is a biggie since configurations can’t be updated when
updating their corresponding templates.&lt;/p&gt;
&lt;h3 id=&quot;alternate-uis&quot;&gt;Alternate UIs&lt;/h3&gt;
&lt;p&gt;We once used to have WYSIWYG UI editors. Now we have to write our UIs
as code in one of any number of frameworks that in turn try to reduce
the toil of writing UIs. It doesn’t have to be this way.&lt;/p&gt;
&lt;p&gt;At least for configuration, just because the configuration is written
down as code doesn’t mean it has to be edited as code. The same UIs that
we once used can still generate those text files.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Vim is actually quite awesome. &lt;a href=&quot;https://neovim.io/&quot;&gt;Neovim&lt;/a&gt; is slightly more or less awesome
depending on who you are ask.&lt;a href=&quot;https://xn--izc.com/posts/code-as-ui/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Promise Fatigue</title>
      <link href="https://xn--izc.com/posts/promise-fatigue/" />
      <updated>2022-11-01T04:03:16Z</updated>
      <id>https://xn--izc.com/posts/promise-fatigue/</id>
      <content xml:lang="en" type="html">
        &lt;ul&gt;
&lt;li&gt;I’ll get it to you by the end of the day.&lt;/li&gt;
&lt;li&gt;I’m working on it right now.&lt;/li&gt;
&lt;li&gt;I’ll get it done today.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though the word “promise” doesn’t appear in any of these, they
still represent a commitment you make to someone else. If you fail to
keep your promise, you will disappoint someone or more than one.&lt;/p&gt;
&lt;p&gt;But if you fail to keep your promises, eventually, you’ll stop
disappointing people. That’s because they no longer expect you to keep
your word. Of course, by then, you would have irreparably damaged your
reputation – and people will no longer consider you as being
reliable.&lt;/p&gt;
&lt;p&gt;Before making a commitment, always think about &lt;strong&gt;promise
fatigue&lt;/strong&gt;. Setting low but realistic expectations is better than
setting high but unrealistic ones.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>The Loss of a Virtuous Culture</title>
      <link href="https://xn--izc.com/posts/the-loss-of-a-virtuous-culture/" />
      <updated>2022-10-28T21:13:19Z</updated>
      <id>https://xn--izc.com/posts/the-loss-of-a-virtuous-culture/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Long ago, around 2011, we had an espresso machine in the Google micro
kitchen – or MK as we called it – near my desk. There were no baristas
at the time, so people made their own. Some folks thought we could use
more sophisticated coffee beans than they had in the MK. A designated
person would purchase these higher-quality beans using money that
everyone collected in a jar in the MK.&lt;/p&gt;
&lt;p&gt;This cash jar was not locked. Instead, it was in a conspicuous
location, along with a note suggesting that people using the “good”
beans should consider dropping some cash there so that people could
continue purchasing premium beans.&lt;/p&gt;
&lt;p&gt;One day, the cash in the jar went missing.&lt;/p&gt;
&lt;p&gt;The response was swift. Donations poured from everywhere in the
office, offering to replace the lost cash. Noone speculated on who took
the money. Things were back to normal as soon as the incident was
reported. The cash jar was re-instated.&lt;/p&gt;
&lt;p&gt;The cynic in me wondered why the money didn’t get stolen sooner. But
everything worked on the honor system at Google. And we were insistent
on keeping it that way.&lt;/p&gt;
&lt;p&gt;As far as I know, the money never went missing again, though the cash
jar system went away as folks moved around inside the ever-expanding
office.&lt;/p&gt;
&lt;p&gt;Cash isn’t used as much anymore. However, would a similar system work
now? We no longer place as much trust in each other as we did. We don’t
even know most of the people we see walking around. But something is
going on beyond that. Even if we did know the people, we are now more
attuned to insider risk – and justifiably so. As a result, there is more
of an air of distrust.&lt;/p&gt;
&lt;p&gt;What would be the consequences of a breakdown in mutual trust among
employees? In &lt;a href=&quot;https://brianlui.dog/2020/10/06/upside-decay/&quot;&gt;“Upside Decay,”&lt;/a&gt;
Brian Lui argues that such a breakdown in virtue limits an
organization’s ability to benefit from luck.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/the-loss-of-a-virtuous-culture/virtuous-cycle.png&quot; alt=&quot;How a culture of virtue increases the likelihood of collaboration outside of their core work.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;How a culture of virtue increases the
likelihood of collaboration outside of their core work.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As the diagram indicates, a virtuous culture cultivates
collaboration, leading to successful extra-curricular activity beyond
their core work, which reinforces the culture. Notably, many of Google’s
successful billion-dollar products came about or benefited from
unexpected collaborations that were more or less luck. In a culture of
mistrust, such associations outside of their core work would never have
happened.&lt;/p&gt;
&lt;p&gt;Leadership can identify, plan, and account for some contingencies in
core work. Non-core work, on the other hand, relies on self organization
within the company. That self organization needs trust. Every large
project owes its existence to this non-core work.&lt;/p&gt;
&lt;p&gt;And that’s not all. Some of this work may well become large products
in their own right. Any large tech company will have tons of stories of
this happening repeatedly.&lt;/p&gt;
&lt;p&gt;The importance of “serendipitous collaboration” isn’t lost on
executives. It is the reason behind many pushes for bringing tech
workers back to the office.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>The Lettergrade Rule</title>
      <link href="https://xn--izc.com/posts/the-lettergrade-rule/" />
      <updated>2022-09-16T00:27:57Z</updated>
      <id>https://xn--izc.com/posts/the-lettergrade-rule/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;How do you know when a code review is “done”?&lt;/p&gt;
&lt;p&gt;Let’s say you are the reviewer and see many small changes you’d like
the author to make. At some point, you’ll agree that the introduced
behavior changes are correct or at least harmless. The remaining
comments are largely stylistic or involve misalignments in minor
architectural choices.&lt;/p&gt;
&lt;p&gt;The letter grade rule is a lens for determining if any remaining
comments justify blocking the change. It goes something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does addressing your comment or doing what you suggest improve the
reviewed code by at least half a letter grade?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Your comments are not worth blocking the review if the answer is no.
Instead, leave them as suggestions that the author can take and do with
it what they will. Then, move on with your life.&lt;/p&gt;
&lt;p&gt;This route is respectful of the author’s time and yours. It also
implicitly places some amount of trust and responsibility on the author,
which is empowering.&lt;/p&gt;
&lt;p&gt;You might now wonder what constitutes a half-a-letter-grade
improvement.&lt;/p&gt;
&lt;p&gt;Here’s a non-exhaustive list of things it is not:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stylistic choices that don’t violate the project’s style guide.
Please choose a coding style and enforce it via a code formatting tool
if this is a common cause of disagreement. Use a code formatting tool
even if it isn’t a common cause of dispute. There should be no reason to
format text with a spacebar in 2022.&lt;/li&gt;
&lt;li&gt;Choice of identifier name; unless the name diverges from the
project’s domain model and naming convention or objectively hurts
readability.&lt;/li&gt;
&lt;li&gt;“This isn’t how I would have done it.”&lt;/li&gt;
&lt;li&gt;There are minor grammar issues or word choices in comments that
don’t decrease the readability of the code. You should be able to trust
the author to make those fixes and submit the change without you having
to do another pass.&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
    <entry>
      <title>All natural numbers are interesting</title>
      <link href="https://xn--izc.com/posts/interesting-numbers/" />
      <updated>2022-08-03T15:50:46Z</updated>
      <id>https://xn--izc.com/posts/interesting-numbers/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;&lt;strong&gt;Theorem&lt;/strong&gt;: All natural numbers are interesting.&lt;a href=&quot;https://xn--izc.com/posts/interesting-numbers/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Proof by contradiction.&lt;/p&gt;
&lt;p&gt;Assume the theorem is false. Then there must be at least one number
&lt;span class=&quot;math inline&quot;&gt;&#92;in &#92;N&lt;/span&gt; that is boring.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let&lt;/strong&gt; &lt;span class=&quot;math inline&quot;&gt;&#92;mathbb{B} &#92;subset
&#92;N&lt;/span&gt; be the set of boring numbers.&lt;/p&gt;
&lt;p&gt;By the assumption, we have:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;mathbb{B} &#92;ne &#92;phi&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Thus, because &lt;span class=&quot;math inline&quot;&gt;&#92;mathbb{B}&lt;/span&gt; is
non-empty &lt;span class=&quot;math inline&quot;&gt;&#92;mathbb{B} &#92;subset &#92;N&lt;/span&gt;, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Well-ordering_principle&quot;&gt;Well
Ordering Principle&lt;/a&gt; tells us that:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;exists b &#92;in &#92;mathbb{B} &#92;| b =
&#92;mathrm{inf}(&#92;mathbb{B})&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Thus this &lt;span class=&quot;math inline&quot;&gt;b&lt;/span&gt; is the smallest boring
natural number in existence; which makes &lt;span class=&quot;math inline&quot;&gt;b&lt;/span&gt; interesting. A contradiction! ∎&lt;/p&gt;
&lt;p&gt;Note that the same doesn’t trivially hold for the set of real numbers
since you’d first have to prove that the set of boring real numbers is
either finite or bounded, and that the infimum is a member of the set.
Neither does this hold for &lt;span class=&quot;math inline&quot;&gt;&#92;Z&lt;/span&gt; since a
non-finite subset in &lt;span class=&quot;math inline&quot;&gt;&#92;Z&lt;/span&gt; doesn’t
necessarily have a minimum.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Not actually a theorem.&lt;a href=&quot;https://xn--izc.com/posts/interesting-numbers/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Use Git hooks to automatically push after every commit</title>
      <link href="https://xn--izc.com/posts/git-autopush/" />
      <updated>2022-07-05T20:15:23Z</updated>
      <id>https://xn--izc.com/posts/git-autopush/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;A Git hook is a shell script that is invoked at specific points
during some Git operations. They are documented in &lt;a href=&quot;https://www.git-scm.com/docs/githooks#_post_commit&quot;&gt;the Git
book&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The hook we are interested in is &lt;code&gt;post-commit&lt;/code&gt; (&lt;a href=&quot;https://www.git-scm.com/docs/githooks#_post_commit&quot;&gt;documented
here&lt;/a&gt;). It gets run after a new commit is made. This is exactly when
we want to try and update our remote.&lt;/p&gt;
&lt;p&gt;Our hook will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Execute each time you commit something into your repository.&lt;/li&gt;
&lt;li&gt;Avoid doing anything if the commit is made during a rebase or
merge.&lt;/li&gt;
&lt;li&gt;Push to a remote named &lt;code&gt;origin&lt;/code&gt; (or whichever one you
change the &lt;code&gt;UPSTREAM&lt;/code&gt; shell variable to point).&lt;/li&gt;
&lt;li&gt;Create or update a remote reference that matches the branch name
that’s currently checked out.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Copy and paste the following script into a file named
&lt;code&gt;.git/hooks/post-commit&lt;/code&gt; in your repository directory.&lt;/p&gt;
&lt;p&gt;IMPORTANT: Afterwards make the script runnable via
&lt;code&gt;chmod +x .git/hooks/post-commit&lt;/code&gt;.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/asankah/a6263bbd6081bffd031ca066e5177df2.js&quot;&gt;&lt;/script&gt;

      </content>
    </entry>
    <entry>
      <title>DARPA&#39;s Heilmeier Catechism</title>
      <link href="https://xn--izc.com/posts/darpa-heilmeier-catechism/" />
      <updated>2022-06-28T14:11:17Z</updated>
      <id>https://xn--izc.com/posts/darpa-heilmeier-catechism/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It seems the hardest part of engineering is the part where you are
staring at a blank page with a vague notion of a problem statement in
your head.&lt;/p&gt;
&lt;p&gt;First you seek structure. After all your attention span can only hold
so much at the same time. In order to tackle larger problems, you need
to reduce large parts of the problem area into intuition. And in turn,
to reduce parts of the problem into intuition, you need to break those
pieces into smaller simpler pieces that you can chew on
individually.&lt;/p&gt;
&lt;p&gt;Losing sight of the forest for the trees is easy during this
process.&lt;/p&gt;
&lt;p&gt;Why were you trying to solve this problem in the first place? Would
you have started if you knew then what you know now about the real scope
of the problem?&lt;/p&gt;
&lt;p&gt;Such concerns are also part of the problem statement; parts that help
your prioritize and select the best solution amongst many. Throughout
all, it’s always good to keep and eye on the prize. That being the end
goal of the exercise. The goal must justify the effort involved. Once
again, for that you need to reduce your motives into intuition.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.darpa.mil/work-with-us/heilmeier-catechism&quot;&gt;“The
Heilmeier Catechism”&lt;/a&gt; is “a set of questions […] to help Agency
officials think through and evaluate proposed research programs”. The
list of questions is duplicated here for your convenience. It’s a short
and terse list. Much like what your design sketch should be.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are you trying to do? Articulate your objectives using
absolutely no jargon.&lt;/li&gt;
&lt;li&gt;How is it done today, and what are the limits of current
practice?&lt;/li&gt;
&lt;li&gt;What is new in your approach and why do you think it will be
successful?&lt;/li&gt;
&lt;li&gt;Who cares? If you are successful, what difference will it make?&lt;/li&gt;
&lt;li&gt;What are the risks?&lt;/li&gt;
&lt;li&gt;How much will it cost?&lt;/li&gt;
&lt;li&gt;How long will it take?&lt;/li&gt;
&lt;li&gt;What are the mid-term and final “exams” to check for success?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(Source &lt;a href=&quot;https://www.darpa.mil/work-with-us/heilmeier-catechism&quot;&gt;The
Heilmeier Catechism - DARPA&lt;/a&gt;).&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Markdown should be readble without knowing Markdown</title>
      <link href="https://xn--izc.com/posts/mark-goes-up-and-down/" />
      <updated>2022-04-05T17:02:12Z</updated>
      <id>https://xn--izc.com/posts/mark-goes-up-and-down/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;&lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax&quot;&gt;Markdown&lt;/a&gt;
started out as a way to write text files that could also be machine
parsed and rendered into a higher fidelity format.&lt;/p&gt;
&lt;p&gt;To quote from the Philosophy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Readability, however, is emphasized above all else. A
Markdown-formatted document should be publishable as-is, as plain text,
without looking like it’s been marked up with tags or formatting
instructions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This particular aspect of the format wasn’t maintained very well.
Immediately following the &lt;em&gt;“Philosophy”&lt;/em&gt; section is &lt;em&gt;“Inline
HTML”&lt;/em&gt; which contradicts the &lt;em&gt;“without looking like it’s been
marked up”&lt;/em&gt; requirement.&lt;/p&gt;
&lt;p&gt;The ease of writing goal was met head on. So much so that it is now
the de-facto format for writing documentation that documents in general
that has any kind of formatting at all. This blog post is also based on
a markdown document.&lt;/p&gt;
&lt;p&gt;People – of course – need more features. And features there were
many. The &lt;em&gt;“Variants”&lt;/em&gt; section of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown#variants&quot;&gt;Wikipedia page on
Markdown&lt;/a&gt; touches upon &lt;em&gt;some&lt;/em&gt; of the popular syntaxes that
exist now.&lt;/p&gt;
&lt;p&gt;On pet-peeve I have is that these new features don’t even try to
adhere to the minimum markup philosophy. And hence just introduce HTML
tags – or worse HTML-like but not HTML tags – into the format. Someone
who’s not familiar with Markdown syntax – or for that matter whatever
dialect you are using for some document – shouldn’t be thrown off by the
additional markup.&lt;/p&gt;
&lt;h2 id=&quot;better-definition-lists&quot;&gt;Better Definition Lists?&lt;/h2&gt;
&lt;p&gt;I really don’t like the &lt;em&gt;“Definition List”&lt;/em&gt; syntax. This
feature isn’t in the original Markdown syntax, but is a part of &lt;a href=&quot;https://www.markdownguide.org/extended-syntax/#definition-lists&quot;&gt;many
extended syntaxes&lt;/a&gt;. It looks like this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode markdown bad&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Some term&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;: The definition of the term. Long lines can be&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  broken down while preserving the indent. But&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  the first character can&amp;#39;t be &amp;#39;:&amp;#39; or it will become&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  *another* definition.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See, it’s easy to see the &lt;code&gt;:&lt;/code&gt; as some misplaced
punctuation rather than markup when just reading the text. Instead how
about maybe this?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode markdown maybe&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;an&quot;&gt;Some term:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  The definition starts here. Long lines can be&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  broken down like this.&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  Maybe continue the definition here.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It looks more like a definition in a regular text file.&lt;/p&gt;
&lt;h2 id=&quot;better-code-blocks&quot;&gt;Better Code Blocks?&lt;/h2&gt;
&lt;p&gt;The original syntax for code blocks is to just add extra space in the
middle, like so:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode markdown good&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;This is normal text.&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    function ThisIsACodeBlock() {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;More normal text.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See, if you saw this in a text file, your eyes would easily follow
the context switch. Instead, the most popular markdown formats use the
following kind of markup:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode markdown bad&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;This is normal text.&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;function ThisIsACodeBlock() {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;More normal text.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See how the markup is in the way? There’s a reason for the special
markup; it allows specification of additional attributes like the
underlying language that the code block is in.&lt;/p&gt;
&lt;p&gt;Instead, how about something like this?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode markdown maybe&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;This is normal text.&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;javascript code:&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    function ThisIsACodeBlock() {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;More normal text.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It re-uses the &lt;code&gt;some text:&lt;/code&gt; syntax that’s used for
specifying links.&lt;/p&gt;
&lt;h2 id=&quot;better-admonitions&quot;&gt;Better admonitions?&lt;/h2&gt;
&lt;p&gt;Admonitions aren’t a feature of regular Markdown. It’s available &lt;a href=&quot;https://python-markdown.github.io/extensions/admonition/&quot;&gt;as an
extension in select Markdown processors&lt;/a&gt;. The syntax is a little
horrendous:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode markdown bad&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;!!! type &amp;quot;optional explicit title within double quotes&amp;quot;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    Any number of other indented markdown elements.&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    This is the second paragraph.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Okay the exclamation points kind of hints at what this is supposed to
mean. But how about this?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode markdown maybe&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;an&quot;&gt;NOTE:&lt;/span&gt;&lt;span class=&quot;co&quot;&gt; Optional explicit title&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    Paragraph that contains extra details about the note.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    This is the second paragraph.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s obvious from looking at the plain text what this is supposed to
be; no need to go look at the documentation for your Markdown dialect to
figure out what on earth &lt;code&gt;!!! title&lt;/code&gt; is supposed to be.&lt;/p&gt;
&lt;h2 id=&quot;better-collapsed-sections&quot;&gt;Better collapsed sections?&lt;/h2&gt;
&lt;p&gt;Okay, so this one is specific to &lt;a href=&quot;https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections&quot;&gt;GitHub
Flavored Markdown&lt;/a&gt;, and it’s terrible. It comes down to the genre of
just writing HTML:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode markdown bad&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&lt;/span&gt;CLICK ME&lt;span class=&quot;dt&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;#### We can hide anything, even code!&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-6&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    ```ruby&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-7&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    puts &amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-8&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;    ```&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-9&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-10&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-11&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb8-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;WTF? You might as well write the thing in HTML and call it a day.
Maybe if they could’ve gone with something like:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode markdown maybe&quot;&gt;&lt;code class=&quot;sourceCode markdown&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Summary goes here.&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-4&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Details:&lt;/span&gt;
&lt;span id=&quot;cb9-5&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  Details go here. and yes you can use fenced code blocks.&lt;/span&gt;
&lt;span id=&quot;cb9-6&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;/span&gt;
&lt;span id=&quot;cb9-7&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;      Like this.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-8&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;      &lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-9&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  Or the ugly way:&lt;/span&gt;
&lt;span id=&quot;cb9-10&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;/span&gt;
&lt;span id=&quot;cb9-11&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;in&quot;&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-12&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;  Like this.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-13&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/mark-goes-up-and-down/#cb9-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;in&quot;&gt;  ```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again it re-uses the &lt;code&gt;some text:&lt;/code&gt; syntax, and it
could probably use either &lt;code&gt;details&lt;/code&gt; or &lt;code&gt;Details&lt;/code&gt;.
Either way, you don’t need to understand the markup to see where this is
going.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>On Gender Gap in Adolescent Mental Health</title>
      <link href="https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/" />
      <updated>2022-03-01T19:51:34Z</updated>
      <id>https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Today is the first day of &lt;a href=&quot;https://www.nationalgeographic.com/history/article/why-the-us-celebrates-womens-history-month-every-march&quot;&gt;Women’s
History Month&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Coincidentally there’s a paper making the rounds titled &lt;em&gt;“The
gender gap in adolescent mental health: A cross-national investigation
of 566,829 adolescents across 73 countries”&lt;/em&gt; &lt;span class=&quot;citation&quot; data-cites=&quot;campbell2021gender&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/#ref-campbell2021gender&quot; role=&quot;doc-biblioref&quot;&gt;Campbell et al., 2021&lt;/a&gt;)&lt;/span&gt;, which makes some
these interesting claims:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Girls have worse average mental health than boys across 4 mental
health measures.&lt;/li&gt;
&lt;li&gt;There is significant heterogeneity in the mental health gender gap
size across countries.&lt;/li&gt;
&lt;li&gt;The gap is most pronounced for psychological distress and life
satisfaction.&lt;/li&gt;
&lt;li&gt;More gender-equal countries have more gender gaps in mental
health.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last point, in particular, is a bit of an eyebrow-raiser. So
let’s have a closer look.&lt;/p&gt;
&lt;p&gt;The study uses the &lt;a href=&quot;https://www.oecd.org/pisa/data/2018database/&quot;&gt;PISA 2018
dataset&lt;/a&gt;, introducing a couple of caveats. Namely:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;All survey respondents were 15 years old; thus, the dataset doesn’t
consider higher education and employment effects.&lt;/li&gt;
&lt;li&gt;The data is from 2018; thus excludes the effects of the pandemic. It
would be interesting to see how the responses change now that people are
coming out of a lengthy lock down.&lt;/li&gt;
&lt;li&gt;Gender was binary. There was no non-binary option.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The study &lt;span class=&quot;citation&quot; data-cites=&quot;campbell2021gender&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/#ref-campbell2021gender&quot; role=&quot;doc-biblioref&quot;&gt;Campbell et al.,
2021&lt;/a&gt;)&lt;/span&gt; derives five measures of mental health based on the
PISA 2018 dataset as follows:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;“Life satisfaction”&lt;/em&gt; measures responses to the question
&lt;em&gt;“on a scale of 0-10, overall, how satisfied are you with your life
as a whole these days?”&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;“Psychological distress”&lt;/em&gt; measures responses to the
question on how often they felt &lt;em&gt;“sad”&lt;/em&gt;, &lt;em&gt;“miserable”&lt;/em&gt;,
&lt;em&gt;“scared”&lt;/em&gt;, and &lt;em&gt;“afraid”&lt;/em&gt; on a scale of &lt;em&gt;“never”&lt;/em&gt;,
&lt;em&gt;“rarely”&lt;/em&gt;, &lt;em&gt;“sometimes”&lt;/em&gt;, and &lt;em&gt;“always”&lt;/em&gt;. Each
response yields points ranging from 1 through 4, respectively. Summing
the points for each question results in a score of 4-16.&lt;/p&gt;
&lt;p&gt;The survey doesn’t appear to have clarified the difference between
&lt;em&gt;“sad”&lt;/em&gt;/&lt;em&gt;“miserable”&lt;/em&gt; and
&lt;em&gt;“scared”&lt;/em&gt;/&lt;em&gt;“afraid”&lt;/em&gt;. PISA 2018 mentions that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All questions were translated into the languages of participating
countries by two independent linguists and then reconciled by a third to
ensure consistent meaning in all countries.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;“Hedonia”&lt;/em&gt; measures the responses to the question on how
often they felt &lt;em&gt;“happy”&lt;/em&gt;, &lt;em&gt;“lively”&lt;/em&gt;, &lt;em&gt;“proud”&lt;/em&gt;,
&lt;em&gt;“joyful”&lt;/em&gt;, and &lt;em&gt;“cheerful”&lt;/em&gt; on the same scale. This
yields a combined scale of 5-20.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;“Eudaemonic wellbeing”&lt;/em&gt; measures the degree of agreement
with the below statements. The scale was &lt;em&gt;“strongly disagree”&lt;/em&gt;,
&lt;em&gt;“disagree”&lt;/em&gt;, &lt;em&gt;“agree”&lt;/em&gt;, and &lt;em&gt;“strongly agree”&lt;/em&gt;
with a combined score in the range 3-12:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;em&gt;“My life has clear meaning or purpose”&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“I have discovered a satisfactory meaning in life.”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“I have a clear sense of what gives meaning to my
life”&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Details of the analysis are in &lt;a href=&quot;https://ars.els-cdn.com/content/image/1-s2.0-S2352827321000173-mmc1.pdf&quot;&gt;the
companion document (PDF link)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In figure S2 of &lt;span class=&quot;citation&quot; data-cites=&quot;campbell2021gender&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/#ref-campbell2021gender&quot; role=&quot;doc-biblioref&quot;&gt;Campbell et al., 2021&lt;/a&gt;)&lt;/span&gt; shows the
distribution of &lt;em&gt;life satisfaction&lt;/em&gt;. Again, developed nations are
not doing well compared with countries like Saudi Arabia.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/life-satisfaction-eu.png&quot; alt=&quot;Distribution of life satisfaction scores for France, Germany, Greece, and Iceland. The range of responses were from 0 through 10. Red is male, and blue is female.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Distribution of life satisfaction scores
for France, Germany, Greece, and Iceland. The range of responses were
from 0 through 10. Red is male, and blue is female.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Compare with:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/life-satisfaction-sa-uae.png&quot; alt=&quot;Distribution of life satisfaction scores for Saudi Arabia and United Arab Emirates. Note that most respondents gave a score of 10.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Distribution of life satisfaction scores
for Saudi Arabia and United Arab Emirates. Note that most respondents
gave a score of 10.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I’m skeptical that these numbers represent reality. Unless there’s a
part of Saudi Arabia where adolescents are consistently happy all the
time, these numbers don’t make sense. My skepticism is also extended to
the data from the UAE. &lt;a href=&quot;https://www.hrw.org/world-report/2021/country-chapters/united-arab-emirates&quot;&gt;Human
Rights Watch’s report on the UAE&lt;/a&gt; indicates that the UAE is far from
having any semblance of gender equality. Approximately 80% of the
population consists of migrant workers &lt;a href=&quot;https://www.aljazeera.com/news/2022/2/21/thousands-of-children-in-uae-has-no-access-to-schooling-report&quot;&gt;who’s
children don’t have access to formal education&lt;/a&gt;. It’s unlikely that
these children of migrants participated in the study.&lt;/p&gt;
&lt;p&gt;The curve fitting for the resulting graphs is what tells the stories
that are summarized at the start of this post. The axes are arranged so
that moving towards the right and moving upwards indicate better
conditions. Hence it’s apparent from the curves that male life
satisfaction is pretty consistent and not affected all that much by
GII&lt;a href=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. Meanwhile, female life satisfaction
trends &lt;em&gt;downward&lt;/em&gt; as GII improves; hence the conclusion that more
gender equality implies less happiness.&lt;/p&gt;
&lt;p&gt;GSNI (Gender Social Norms Index) is also negatively correlated with
quality-of-life measures (where we put “good” on the high end and “bad”
on the low end).&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/life-satisfaction-vs-other-indicators.png&quot; alt=&quot;Life satisfaction plotted against per-capita GDP, Gini index, GII, GSNI, GGGI. The curves don’t quite fit very well.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Life satisfaction plotted against
per-capita GDP, Gini index, GII, GSNI, GGGI. The curves don’t quite fit
very well.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;All the graphs show a high variance. Only a small number of countries
are present in the study. And whether the subjects of the study are
representative of the population is in doubt. Overall I find the study
unconvincing.&lt;/p&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-campbell2021gender&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Campbell, O. L., Bann, D., &amp;amp; Patalay, P. (2021). The gender gap in
adolescent mental health: A cross-national investigation of 566,829
adolescents across 73 countries. &lt;em&gt;SSM-Population Health&lt;/em&gt;,
&lt;em&gt;13&lt;/em&gt;, 100742.
&lt;/div&gt;
&lt;/div&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;GII is the Gender Inequality Index. It’s based on such
factors like &lt;em&gt;female and male shares of parliamentary seats&lt;/em&gt;,
&lt;em&gt;female and male population with at least secondary education&lt;/em&gt;,
&lt;em&gt;female and male labour force participation rates&lt;/em&gt;, &lt;em&gt;maternal
mortality ratio&lt;/em&gt;, and &lt;em&gt;adolescent birth rate&lt;/em&gt;.&lt;a href=&quot;https://xn--izc.com/posts/gender-gap-in-adolescent-mental-health/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>On Highlighting Syntax vs. Semantics</title>
      <link href="https://xn--izc.com/posts/syntax-highlighting/" />
      <updated>2022-02-12T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/syntax-highlighting/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;&lt;span class=&quot;noun&quot;&gt;Aesthetics&lt;/span&gt; &lt;span class=&quot;adverb&quot;&gt;aside&lt;/span&gt;, &lt;span class=&quot;noun&quot;&gt;syntax&lt;/span&gt; &lt;span class=&quot;gerund&quot;&gt;highlighting&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;noun&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;performs&lt;/span&gt; &lt;span class=&quot;determiner&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;important&lt;/span&gt;
&lt;span class=&quot;noun&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;gerund&quot;&gt;improving&lt;/span&gt; the &lt;span class=&quot;noun&quot;&gt;readability&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;of&lt;/span&gt;
&lt;span class=&quot;noun&quot;&gt;code&lt;/span&gt;. &lt;span class=&quot;adjective&quot;&gt;Most&lt;/span&gt;
&lt;span class=&quot;adjective&quot;&gt;syntax&lt;/span&gt; &lt;span class=&quot;gerund&quot;&gt;highlighting&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;schemes&lt;/span&gt;
&lt;span class=&quot;gerund&quot;&gt;including&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;popular&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;libraries&lt;/span&gt;
&lt;span class=&quot;verb&quot;&gt;are&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;limited&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;gerund&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;colors&lt;/span&gt; &lt;span class=&quot;conjunction&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;gerund&quot;&gt;formatting&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;changes&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;distinguish&lt;/span&gt;
&lt;span class=&quot;preposition&quot;&gt;between&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;different&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;syntax&lt;/span&gt;
&lt;span class=&quot;noun&quot;&gt;classes&lt;/span&gt;. &lt;span class=&quot;pronoun&quot;&gt;This&lt;/span&gt;
&lt;span class=&quot;verb&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;determiner&quot;&gt;what&lt;/span&gt; &lt;span class=&quot;pronoun&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;would look&lt;/span&gt; &lt;span class=&quot;conjunction&quot;&gt;like&lt;/span&gt; &lt;span class=&quot;conjunction&quot;&gt;if&lt;/span&gt;
&lt;span class=&quot;pronoun&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;determiner&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;logic&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;proper&quot;&gt;English&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;prose&lt;/span&gt;. &lt;span class=&quot;adjective&quot;&gt;Each&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;preposition&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;pronoun&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;paragraph&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;adverb&quot;&gt;highlighted&lt;/span&gt; &lt;span class=&quot;verb&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;pronoun&quot;&gt;its&lt;/span&gt; &lt;span class=&quot;adjective&quot;&gt;respective&lt;/span&gt;
&lt;span class=&quot;adjective&quot;&gt;syntactic&lt;/span&gt; &lt;span class=&quot;noun&quot;&gt;purpose&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Not very readable, is it? The colors aren’t random. They highlights
correspond to &lt;span class=&quot;noun&quot;&gt;noun&lt;/span&gt;, &lt;span class=&quot;adverb&quot;&gt;adverb&lt;/span&gt;, &lt;span class=&quot;gerund&quot;&gt;gerund&lt;/span&gt;, &lt;span class=&quot;preposition&quot;&gt;preposition&lt;/span&gt;, &lt;span class=&quot;adjective&quot;&gt;adjective&lt;/span&gt;, and &lt;span class=&quot;verb&quot;&gt;verb&lt;/span&gt;.
This is basically how people use syntax highlighting.&lt;/p&gt;
&lt;p&gt;Typographers have long known that punctuation alone can’t
sufficiently convey emphasis and relative importance of prose. As &lt;span class=&quot;citation&quot; data-cites=&quot;truss2004eats&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/syntax-highlighting/#ref-truss2004eats&quot; role=&quot;doc-biblioref&quot;&gt;Truss, 2004&lt;/a&gt;)&lt;/span&gt;
points out &lt;em&gt;italics&lt;/em&gt; is &lt;em&gt;“the print equivalent of
underlining”&lt;/em&gt; (via &lt;span class=&quot;citation&quot; data-cites=&quot;wiki:Italic_type&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/syntax-highlighting/#ref-wiki:Italic_type&quot; role=&quot;doc-biblioref&quot;&gt;Wikipedia, 2021&lt;/a&gt;)&lt;/span&gt;). A number of uses
exist for this font variation including providing emphasis, stressing
important points, or indicating foreign words and phrases. When
conveying emphasis the syntactic role of a word does not change; the
word just is &lt;em&gt;more&lt;/em&gt; important to make the central point than
others.&lt;/p&gt;
&lt;p&gt;These key important words alone can’t convey a story. Grammar and
completeness demand accompanying words. It is the role of formatting,
whitespace, and punctuation to guide the reader towards what is
important. Without formatting and whitespace, prose would become an
intimidating “wall of words”; tedious and unwelcoming.&lt;/p&gt;
&lt;p&gt;And so it goes for code; some code is more important than others. The
central logic of a snippet of code lies somewhere in the middle
surrounded by boilerplate, setup, and tear down logic. If syntax
highlighting were to make the central logic stand out, then it has to go
beyond mere syntactic purpose of the tokens comprising the code.&lt;/p&gt;
&lt;p&gt;What would such a scheme look like?&lt;/p&gt;
&lt;pre&gt;
 bool ListValue::&lt;span class=&quot;function hi&quot;&gt;Set&lt;/span&gt;(size_t &lt;span class=&quot;var-index&quot;&gt;index&lt;/span&gt;, std::unique_ptr&amp;lt;Value&amp;gt; &lt;span class=&quot;var-value&quot;&gt;in_value&lt;/span&gt;) {
   if (!in_value)
     return false;
   if (index &gt;= list().size())
     list().resize(index + 1);

   &lt;span class=&quot;hi&quot;&gt;&lt;span class=&quot;function&quot;&gt;list&lt;/span&gt;()[&lt;span class=&quot;var-index&quot;&gt;index&lt;/span&gt;] = std::&lt;span class=&quot;function&quot;&gt;move&lt;/span&gt;(*&lt;span class=&quot;var-value&quot;&gt;in_value&lt;/span&gt;);&lt;/span&gt;

   return true;
 }
&lt;/pre&gt;
&lt;p&gt;Perhaps not the best example, but you should get the gist of where
I’m going with this. The highlighting quickly directs your eyes to the
parts that need attention. You’d still need to do the legwork for the
details. But for someone trying to figure out what some undocumented
function is doing, this kind of highlight makes quick work of going past
the boilerplate.&lt;/p&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-truss2004eats&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Truss, L. (2004). &lt;em&gt;Eats, shoots &amp;amp; leaves: The zero tolerance
approach to punctuation&lt;/em&gt; (p. 146). Penguin.
&lt;/div&gt;
&lt;div id=&quot;ref-wiki:Italic_type&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
Wikipedia. (2021). &lt;em&gt;&lt;span class=&quot;nocase&quot;&gt;Italic type&lt;/span&gt; —
&lt;span&gt;W&lt;/span&gt;ikipedia&lt;span&gt;,&lt;/span&gt; the free encyclopedia&lt;/em&gt;. &lt;a href=&quot;http://en.wikipedia.org/w/index.php?title=Italic%20type&amp;amp;oldid=1049142359&quot; class=&quot;uri&quot;&gt;http://en.wikipedia.org/w/index.php?title=Italic%20type&amp;amp;oldid=1049142359&lt;/a&gt;.
&lt;/div&gt;
&lt;/div&gt;

      </content>
    </entry>
    <entry>
      <title>Inktober - Stripes</title>
      <link href="https://xn--izc.com/posts/inktober-stripes/" />
      <updated>2022-01-21T22:20:38Z</updated>
      <id>https://xn--izc.com/posts/inktober-stripes/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/inktober-stripes/inktober-stripes.png&quot; alt=&quot;“Stripes” - A bee wearing an incorrectly striped sweater&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;“Stripes” - A bee wearing an incorrectly
striped sweater&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For &lt;a href=&quot;https://inktober.com/inktober52&quot;&gt;Inktober 52&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Inktober - Wild</title>
      <link href="https://xn--izc.com/posts/inktober-wild/" />
      <updated>2022-01-13T20:35:39Z</updated>
      <id>https://xn--izc.com/posts/inktober-wild/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/inktober-wild/inktober-wild.png&quot; alt=&quot;“Wild” - Caught in the wild&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;“Wild” - Caught in the wild&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For &lt;a href=&quot;https://inktober.com/inktober52&quot;&gt;Inktober 52&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Inktober - Decay</title>
      <link href="https://xn--izc.com/posts/inktober-decay/" />
      <updated>2022-01-13T20:21:37Z</updated>
      <id>https://xn--izc.com/posts/inktober-decay/</id>
      <content xml:lang="en" type="html">
        &lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/inktober-decay/inktober-decay.png&quot; alt=&quot;“Decay” - I was kind of going for tooth-decay caused by tiny little gremlins.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;“Decay” - I was kind of going for
tooth-decay caused by tiny little gremlins.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For &lt;a href=&quot;https://inktober.com/inktober52&quot;&gt;Inktober 52&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Quickly grab a snapshot of your reMarkable tablet</title>
      <link href="https://xn--izc.com/posts/grab-diagram-workflow-re2/" />
      <updated>2022-01-06T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/grab-diagram-workflow-re2/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;One everyday workflow that I wanted to optimize was quickly sketching
out a diagram on the reMarkable tablet and including it in a document I
was writing somewhere else.&lt;/p&gt;
&lt;p&gt;My primary computer is a Mac. Here’s my solution:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Set up &lt;a href=&quot;https://github.com/asankah/reSnap&quot;&gt;&lt;code&gt;reSnap&lt;/code&gt;&lt;/a&gt;. This
step requires changes on both the reMarkable tablet and the local
machine. For the former, I followed the instructions in the &lt;a href=&quot;https://github.com/asankah/reSnap#readme&quot;&gt;&lt;code&gt;README&lt;/code&gt;&lt;/a&gt;
file. For the latter, I only really needed to install &lt;a href=&quot;https://www.ffmpeg.org/&quot;&gt;&lt;code&gt;FFmpeg&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://imagemagick.org/index.php&quot;&gt;&lt;code&gt;ImageMagick&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a Mac Quick Action to invoke reSnap.&lt;/li&gt;
&lt;li&gt;Bind a hotkey that grabs the snapshot of the reMarkable display,
cleans it up, and sticks it in Mac’s clipboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Details instructions follow. I can now just hit ⌘+⌃+⇧+P to grab the
snapshot and then hit ⌘+V to paste it into whatever application I am
using, usually Google Docs.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-resnap&quot;&gt;Setting up &lt;code&gt;reSnap&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I have &lt;a href=&quot;https://github.com/asankah/reSnap&quot;&gt;my fork of
&lt;code&gt;reSnap&lt;/code&gt;&lt;/a&gt;, which adds a few valuable tricks like cleaning
up the image and placing it in the system clipboard. By default, the
upstream &lt;code&gt;reSnap&lt;/code&gt; script attempts to preview the image using
&lt;code&gt;feh&lt;/code&gt; (an image viewer I’ve never heard of). Immediately
viewing the picture wasn’t useful to me, so I made that optional. You
can grab my fork of reSnap &lt;a href=&quot;https://github.com/asankah/reSnap&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the reMarkable tablet side, you must follow the instructions in
the &lt;code&gt;README&lt;/code&gt; file to install &lt;code&gt;lz4&lt;/code&gt; and
&lt;code&gt;head&lt;/code&gt; on the device.&lt;/p&gt;
&lt;p&gt;It is important to set up SSH to use password-less logins since the
hotkey method relies on being able to connect without prompting for a
password. See instructions for &lt;a href=&quot;https://remarkablewiki.com/tech/ssh#passwordless_login_with_ssh_keys&quot;&gt;setting
up SSH for passwordless login&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the local machine – which in my case is a Mac – you can install
all the requirements using Homebrew as follows:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;brew&lt;/span&gt; install ffmpeg imagemagick&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;creating-a-mac-quick-action&quot;&gt;Creating a Mac Quick Action&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Start “Automator.” &lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/automator-icon.png&quot; alt=&quot;Automator application icon.&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new “Quick Action.” &lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/quick-action-icon.png&quot; alt=&quot;Select “Quick Action” from the “New” menu.&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up the workflow options to receive no input in any
application. All the other options are up to you, or you can leave them
as-is. &lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/workflow-options.png&quot; alt=&quot;Set the workflow options to recieve “no input” in “any application”.&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drag over the “Run Shell Script” action from the actions library.
&lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/run-shell-script-action.png&quot; alt=&quot;Drag over the “Run Shell Script” action.&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste something like the following (with the suggested
modifications to suit your local environment).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;/usr/bin/env&lt;/span&gt; PATH=/bin:/usr/bin:/usr/local/bin:/sbin /path/to/reSnap/reSnap.sh &lt;span class=&quot;at&quot;&gt;--sketch&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--copy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that the reMarkable needs to be connected via a USB cable to
capture a snapshot using the above command. If you want to be able to
use WiFi you should use the &lt;code&gt;--host&lt;/code&gt; option to specify either
the local hostname (usually “remarkable”) or the IP address. In all
cases the hotkey should only be expected to work when the reMarkable is
not sleeping.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you’d like, you can also add a “Display Notification” action,
so you know when the script is done running. The &lt;code&gt;FFMpeg&lt;/code&gt;
invocation may take a few seconds.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Try it out with the “Run” button.&lt;/p&gt;
&lt;h2 id=&quot;binding-a-hotkey&quot;&gt;Binding a hotkey&lt;/h2&gt;
&lt;p&gt;Once you save your quick action, you can bind a hotkey like this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Open “System Preferences” and navigate to “Keyboard” -&amp;gt;
“Shortcuts”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on “Services” and scroll to the bottom. You should see the
new quick action you just made listed under the “General” category. It
should have no keys assigned to it.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/keyboard-shortcuts.png&quot; alt=&quot;Example of what you should see when you select “Services” in “Keyboard” -&amp;gt; “Shortcuts”&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Example of what you should see when you
select “Services” in “Keyboard” -&amp;gt; “Shortcuts”&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Double click on the “none” and type your hotkey.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it.&lt;/p&gt;
&lt;p&gt;Here’s what a snapshot looks like:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/grab-diagram-workflow-re2/snapshot-from-remarkable.png&quot; alt=&quot;A snapshot from my reMarkable tablet&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A snapshot from my reMarkable
tablet&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;a-couple-of-notes-on-the---sketch-option&quot;&gt;A couple of notes on
the &lt;code&gt;--sketch&lt;/code&gt; option&lt;/h2&gt;
&lt;p&gt;My fork of &lt;code&gt;reSnap&lt;/code&gt; introduces a &lt;code&gt;--sketch&lt;/code&gt;
option that cleans up the picture a little bit. It currently does the
following:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Erase the little menu widget from the top-left corner of the image.
Since &lt;code&gt;reSnap&lt;/code&gt; grabs the image right off the framebuffer this
little artifact makes its way to the resulting image.&lt;/li&gt;
&lt;li&gt;Erase a tiny little black dot that appears in the bottom-left corner
of the image. I don’t know where this one comes from, but it’s
there.&lt;/li&gt;
&lt;li&gt;Make the background transparent.&lt;/li&gt;
&lt;li&gt;Resample the image at 50% resolution with anti-aliasing. The
original image is a stiff monochrome image with a white background and
black strokes. The resampling after making the background transparent
makes the edges smoother and a bit easier on the eyes. Otherwise all the
edges look jagged.&lt;/li&gt;
&lt;li&gt;Trim the image to remove all the empty borders thus making the image
size just large enough to hold the actual image.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All of this is done via an invocation of &lt;a href=&quot;https://imagemagick.org/index.php&quot;&gt;ImageMagick&lt;/a&gt;.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Note-taking on a reMarkable 2</title>
      <link href="https://xn--izc.com/posts/remarkable-first-impressions/" />
      <updated>2021-12-30T21:10:30Z</updated>
      <id>https://xn--izc.com/posts/remarkable-first-impressions/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;After much dillydallying about which note-taker/ebook reader I wanted
to get, I went ahead and got a &lt;a href=&quot;https://remarkable.com/&quot;&gt;reMarkable 2&lt;/a&gt;. I’ve been using it for
about a month now. I must say that it’s the closest thing to writing on
paper that I have encountered.&lt;/p&gt;
&lt;p&gt;My requirements of a note-taking tablet were:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Replace my paper notebooks.&lt;/li&gt;
&lt;li&gt;Quickly transfer diagrams and drawings to the computer/laptop.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Replacing a paper notebook is a tall order. A paper notebook is …&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ready as soon as I open it.&lt;/li&gt;
&lt;li&gt;Lightweight.&lt;/li&gt;
&lt;li&gt;Durable.&lt;/li&gt;
&lt;li&gt;Can be used with a comfortable pen.&lt;/li&gt;
&lt;li&gt;Doesn’t make my eyes tired.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;an-unsuccessful-attempt-with-a-pixelbook&quot;&gt;An Unsuccessful
Attempt With A Pixelbook&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/remarkable-first-impressions/picture-of-pixelbook.png&quot; class=&quot;noinvert&quot; alt=&quot;A Pixelbook like this was my first attempt at using a tablet for note-taking. (Image source)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;A Pixelbook like this was my first
attempt at using a tablet for note-taking. &lt;a href=&quot;https://www.google.com/chromebookdevice/google-pixelbook/&quot;&gt;(Image
source)&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;NOTE: The comments below &lt;em&gt;only&lt;/em&gt; apply to the Chromebook
Pixel’s utility as a note-taking device. It is, of course, far more than
a note-taking device and will likely be a better choice for you if you
want to use the web, consume lots of eBooks, or otherwise need the
functionality of a modern laptop.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.google.com/chromebook/device/google-pixelbook/&quot;&gt;Pixelbook&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/remarkable-first-impressions/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; was my first attempt at using a
tablet for note-taking. Unfortunately, while it had other advantages,
the Pixelbook falls far short on convenience.&lt;/p&gt;
&lt;p&gt;Ad-hoc note-taking is a hassle. Getting started requires logging in.
There are good reasons for needing signing-in, and it does have an
option to use the built-in sketch app from the lock screen using the
Pixelbook pen. But the sketch app doesn’t suffice as a note-taking
app.&lt;/p&gt;
&lt;p&gt;I do like the privacy model of the Pixelbook’s lock screen sketch app
– namely, that the note drops into a black box that only the owner can
open. However, I wish the reMarkable could have a feature where adding a
new note doesn’t simultaneously require viewing every note on the
device.&lt;/p&gt;
&lt;p&gt;Once folded over, I get paranoid about the keys underneath. Can I
place it on a table without worrying too much? It’s anxiety-inducing.
It’s also a laptop, which means that someone who’s easily distracted
would be … easily distracted.&lt;/p&gt;
&lt;p&gt;So over to the reMarkable…&lt;/p&gt;
&lt;h2 id=&quot;moderate-success-with-the-remarkable-2&quot;&gt;Moderate Success With
The Remarkable 2&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/remarkable-first-impressions/picture-of-re2.png&quot; class=&quot;noinvert&quot; alt=&quot;The reMarkable 2 was my next choice. (Image Source)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The reMarkable 2 was my next choice. &lt;a href=&quot;https://remarkable.com/&quot;&gt;(Image Source)&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;First of all, this is a note-taking device. You should not expect
much more from it. I thought it would make for a good ebook reader and
journal article reader – it is neither. Its support for ebooks is
limited to PDFs and EPUBs.&lt;/p&gt;
&lt;p&gt;I’m still looking for a satisfactory method of keeping a set of
journal articles synchronized between my laptop and the reMarkable
tablet. The current method is to go through their proprietary cloud
service, which I can only do for my personal usage but not for work.&lt;/p&gt;
&lt;p&gt;Once again, &lt;strong&gt;this is neither a laptop nor an ebook
reader&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There are, however, two important points to note about the reMarkable
tablet:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;It’s the closest I’ve seen to writing on paper. The hardware is
pretty much spot on.&lt;/li&gt;
&lt;li&gt;There’s an active community of hackers who constantly push the
tablet’s capabilities.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The second point bears repeating. The biggest thing going for the
reMarkable tablet right now is the developer community surrounding it.
Have a gander at the &lt;a href=&quot;https://remarkablewiki.com/&quot;&gt;reMarkableWiki&lt;/a&gt;’s &lt;a href=&quot;https://remarkablewiki.com/tips/start&quot;&gt;Tips and Tricks&lt;/a&gt; page or
the &lt;a href=&quot;https://github.com/reHackable/awesome-reMarkable&quot;&gt;Awesome
reMarkable&lt;/a&gt; list. Some highlights include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ability to use third-party clouds or local storage for synchronizing
your reMakable documents (via &lt;a href=&quot;https://remarkablewiki.com/tips/rclone&quot;&gt;rclone&lt;/a&gt; or &lt;a href=&quot;https://github.com/simonschllng/rm-sync&quot;&gt;rm-sync&lt;/a&gt; or many other
options).&lt;/li&gt;
&lt;li&gt;Setting up an email address to which you can email documents which
will appear on your reMarkable (via &lt;a href=&quot;https://remarkablenewsletter.com/&quot;&gt;reMarkable
Newsletter&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Stream your reMarkable screen (via &lt;a href=&quot;https://blog.afandian.com/2020/10/pipes-and-paper-remarkable/&quot;&gt;pipes
and paper&lt;/a&gt;, &lt;a href=&quot;https://github.com/rien/reStream&quot;&gt;reStream&lt;/a&gt;,
&lt;a href=&quot;https://github.com/bordaigorl/rmview&quot;&gt;rMview&lt;/a&gt;, or
others).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are into tinkering with electronics, the reMarkable will
provide ample entertainment in addition to note-taking.&lt;/p&gt;
&lt;h2 id=&quot;workflows&quot;&gt;Workflows&lt;/h2&gt;
&lt;p&gt;The process of making myself at home with the reMarkable 2 involved
coming up with good workflows for the things that I want to do with it.
My goal here is to reduce the overhead as much as possible. Although a
paper notebook is close to ideal for writing things down, it’s not easy
to get that content out to an electronic format. I hope that the
reMarkable 2 will keep the former as-is while significantly improving
the latter.&lt;/p&gt;
&lt;p&gt;Not all notes are equal. Some are ad-hoc sketches and doodles. Some
need to be a bit more longevity, like daily diary entries. Some are
drafts of design documents, diagrams, or blog posts that I’d need to
move over to an electronic format. Then there are work-related things
like interview notes and meeting notes. So we have three overall
workflows:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Missives that I may want to keep around only to satisfy some sort of
hoarding instinct.&lt;/li&gt;
&lt;li&gt;Notes that I want to transcribe into some electronic form. If the
originals are to be kept, they must be labeled or categorized somehow.
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Pictures or diagrams.&lt;/li&gt;
&lt;li&gt;Text.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;Notes that, regardless of whether any transcription is needed, carry
confidential or proprietary information.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of these, the first one is trivial. Pull out the device, write stuff,
move on with life. If necessary, I can always look at the recent notes,
but I will likely never look at anything older than a month.&lt;/p&gt;
&lt;p&gt;The second one is easy if you are using the &lt;a href=&quot;https://remarkable.com/store/connect&quot;&gt;Connect cloud&lt;/a&gt;. There are
multiple integrations that they already have for moving content to other
cloud providers, including conversion to different image formats. The
Connect cloud also handles the work of extracting text from what you’ve
written. In my experience, the handwriting recognition results have been
quite good though they require the occasional cleanup.&lt;/p&gt;
&lt;p&gt;The third one is tricky. Again, sidestepping the Connect cloud
offering, the aforementioned hacking resources really help get material
from the device onto your machine.&lt;/p&gt;
&lt;p&gt;I’ll leave the details for another blog post, but the gist of it is
that we can quickly transfer the contents of the display as a picture to
a laptop or desktop computer via Wifi or via USB. From there, you can
use any number of tools to extract the text or clean up the drawings.
With a little bit of automation, the process was more accessible than
the Connect cloud.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Writing is as close to writing on a paper as one could
get.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tight integration with their cloud offering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great ecosystem of hackers who push the capabilities of the
device far beyond the stock software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The device lasts for days on a single charge. Their marketing
materials mention two weeks. I haven’t pushed it that far due to
occasionally connecting it to the laptop via USB for content transfer. I
can, however, say that based on the battery remaining this claim seems
to be correct in my case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can’t do much else other than note taking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Relatively cheap compared to other note-taking devices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The nib on the pen wears out quickly.&lt;/p&gt;
&lt;p&gt;They do include 9 additional nibs in the package, but I suspect that
I’ll be buying more within a few months. Compare that with something
like &lt;a href=&quot;https://supernote.com/pages/feelwrite-self-recovery-soft-film-technology&quot;&gt;Supernote&lt;/a&gt;
which boasts that their nibs provide the same level of paper-like
friction without as much wear.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires a lot of hand tinkering unless you subscribe to their
cloud offering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limited support for ebook formats mean that you likely can’t read
your purchased ebooks on this device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No support for labeling or organizing your notes – as of this
writing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;In case the Pixelbook site goes offline, here’s the
Wayback Machine’s &lt;a href=&quot;https://web.archive.org/web/20210725184512/https://www.google.com/chromebook/device/google-pixelbook/&quot;&gt;snapshot
from when I wrote this article&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/posts/remarkable-first-impressions/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Why &#39;Strong Opinions Weekly Held&#39;</title>
      <link href="https://xn--izc.com/posts/why-strong-opinions-weekly-held/" />
      <updated>2021-09-28T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/why-strong-opinions-weekly-held/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Previously on this blog I wrote a short note on &lt;a href=&quot;https://xn--izc.com/posts/why-strong-opinions-weekly-held/posts/why-strong-opinions-weakly-held/&quot;&gt;Why Strong Opinions Weakly
Held&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m trying to get something out every week. Hence the new blog
title.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Visualizing A Million People</title>
      <link href="https://xn--izc.com/posts/visualizing-people-2/" />
      <updated>2021-09-06T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/visualizing-people-2/</id>
      <content xml:lang="en" type="html">
        &lt;div class=&quot;preface&quot;&gt;
&lt;p&gt;This article was formerly published as &lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/&quot;&gt;Visualizing Internet Users&lt;/a&gt;. This
version is more generalized and up-to-date.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;What if you introduce a bug and/or a feature that pisses off a
million people?&lt;/p&gt;
&lt;p&gt;The scenario isn’t all that hard to imagine these days if you work at
a big tech company or even a small one with a considerable user base. It
seems a million users aren’t all that hard to reach these days.&lt;/p&gt;
&lt;p&gt;What is harder though is to imagine what a million people looks like.
What if you were being stared down by the entirety of the affected user
base? Or worse you had to stand on a stage in front of them and explain
yourself?&lt;/p&gt;
&lt;p&gt;If you have 1 billion users and you ship a bug that only manifests 1
in a million times, then you have yourself 1000 angry users. It’s good
to know what that group looks like.&lt;/p&gt;
&lt;p&gt;We can easily imagine a single person, 10, or even 25 people. But
exceed a couple of hundred and our imagination falters. It becomes just
a number and stops feeling like “users” or “people.” The perceived
significance of the population thus starts to diminish.&lt;/p&gt;
&lt;h1 id=&quot;so-whats-the-significance-of-a-million-people-anyway&quot;&gt;So what’s
the significance of a million people anyway?&lt;/h1&gt;
&lt;p&gt;World population is teetering on roughly 7.7 billion people (in
2019). So &lt;strong&gt;a million people is about 0.01% of the global
population&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/world-population-2021.png&quot; alt=&quot;Figure 1: World population in 2021 is 7.7 billion approximately.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Figure 1: World population in 2021 is 7.7
billion approximately.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Internet users, on the other hand, come up to something like half of
the world population based World Bank figures which &lt;em&gt;imply&lt;/em&gt; that
roughly 50% of the population should have internet access in 2021 &lt;a href=&quot;https://xn--izc.com/posts/visualizing-people-2/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/worldbank-individuals-using-internet.webp&quot; alt=&quot;Figure 2: Percentage of population who has access to the internet (World Bank 2017)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Figure 2: Percentage of population who
has access to the internet (World Bank 2017)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So &lt;strong&gt;a million users would be 0.02% of the population with some
access to the internet&lt;/strong&gt;. Still not that big.&lt;/p&gt;
&lt;p&gt;But once you focus on a smaller scale like a geographic region or a
user base of some application, then suddenly the million users looks
much bigger.&lt;/p&gt;
&lt;h2 id=&quot;to-49&quot;&gt;1 to 49&lt;/h2&gt;
&lt;p&gt;Let’s skip this range since this is in the range of what you’d see in
a mirror, can fit on a bicycle, can fit on a sofa, your team, gathering
of friends, significant annual family event, or other familiar
situation.&lt;/p&gt;
&lt;h2 id=&quot;from-50-to-100000&quot;&gt;From 50 to 100,000&lt;/h2&gt;
&lt;p&gt;An example of visualizing populations for small numbers can be found
at &lt;a href=&quot;https://blog.lime.link/visualizing-crowd-sizes/&quot;&gt;Visualizing
Crowd Sizes&lt;/a&gt;. It goes from around 50 people up to 100,000 people.&lt;/p&gt;
&lt;p&gt;While 100,000 is interesting we need to go all the way to 1
million.&lt;/p&gt;
&lt;h2 id=&quot;section&quot;&gt;200,000&lt;/h2&gt;
&lt;p&gt;200,000 was the estimated number of people who attended the &lt;a href=&quot;https://marchforourlives.com/&quot;&gt;March for Our Lives&lt;/a&gt; in D.C..
There aren’t any photos capturing &lt;em&gt;all&lt;/em&gt; attendees in one shot,
but there are numerous pictures in &lt;a href=&quot;https://www.cbsnews.com/news/march-for-our-lives-crowd-size-estimated-200000-people-attended-d-c-march/&quot;&gt;this
CBS News article&lt;/a&gt; to give you a good idea.&lt;/p&gt;
&lt;p&gt;In more terrible examples, &lt;a href=&quot;https://www.dw.com/en/more-than-200000-indonesians-protest-governor-purnamas-alleged-blasphemy/a-36611145&quot;&gt;this
article on dw.com&lt;/a&gt; suggests that the crowd size pictured is roughly
around 200,000 people.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;More than 200,000 conservative Muslims gathered in Indonesia’s
capital Jakarta on Friday to protest against the city’s Christian
governor, who is facing trial for blasphemy, police estimated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/dw-com-indonesia-protest-2020-11-20.jpg&quot; alt=&quot;Image from dw.com of a protest in Indonesia allegedly showing 200,000 people. Image Source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Image from dw.com of a protest in
Indonesia allegedly showing 200,000 people. &lt;a href=&quot;https://www.dw.com/en/more-than-200000-indonesians-protest-governor-purnamas-alleged-blasphemy/a-36611145&quot;&gt;Image
Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;section-1&quot;&gt;250,000&lt;/h2&gt;
&lt;p&gt;The March on Washington in 1963– an &lt;em&gt;“event focused on employment
discrimination, civil rights abuses against African Americans, Latinos,
and other disenfranchised groups, and support for the Civil Rights Act
that the Kennedy Administration was attempting to pass through
Congress”&lt;/em&gt; – drew an estimated 250,000 people according to the
National Park Service.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rustin coordinated a staff of over 200 civil rights activists and
organizers to assist in publicizing the march and recruiting marchers,
organizing churches to raise money, coordinating buses and trains, and
administering all of the other logistical details. In many ways, the
March defied expectations. The number of people that attended exceeded
the initial estimates made by the organizers. Rustin had indicated that
they expected over 100,000 people to attend - the final estimate was
250,000, 190,000 blacks and 60,000 whites.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(From &lt;a href=&quot;https://www.nps.gov/articles/march-on-washington.htm&quot;&gt;March on
Washington for Jobs and Freedom – National Parks Service&lt;/a&gt;)&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/march-on-washington-1963.jpg&quot; alt=&quot;Image from nps.gov showing the crowd estimated to be around 250,000 people at the March on Washington on August 28, 1963. See Image Source for full resolution image.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Image from nps.gov showing the crowd
estimated to be around 250,000 people at the March on Washington on
August 28, 1963. See &lt;a href=&quot;https://www.loc.gov/resource/ppmsca.37248/&quot;&gt;Image Source for full
resolution image.&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;section-2&quot;&gt;500,000&lt;/h2&gt;
&lt;p&gt;We are heading into shaky ground here. A 800*600 picture only
contains 480,000 pixels. So we are now reduced to indicating population
by inference. It is no longer possible to capture 500,000 people in a
webpage sized picture while showing each person individually.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.reddit.com/r/philadelphia/comments/3by9g8/if_this_is_what_500k_people_look_like_xpost_from/&quot;&gt;This
Reddit post&lt;/a&gt; claims that there are 500k people in the picture, but I
couldn’t readily find any good references backing up that claim.&lt;/p&gt;
&lt;p&gt;Another event that drew 500,000 people is &lt;a href=&quot;https://www.nbcnews.com/show-me/video/nearly-500-000-people-march-in-anti-violence-rally-in-barcelona-1033617987741&quot;&gt;an
anti-violence rally in Barcelona as reported by NBC&lt;/a&gt;. While there’s
video, the content doesn’t quite capture the massive number of people.
Also it’s &lt;em&gt;“nearly 500,000”&lt;/em&gt; people.&lt;/p&gt;
&lt;p&gt;However, the closest we’ll probably get to a somewhat believable
500,000 person crowd would be the March for Science. They posted the
following picture on &lt;a href=&quot;https://www.facebook.com/marchforscience/posts/836983043362678&quot;&gt;Facebook&lt;/a&gt;
noting that “There are 500,000 people on strike in Montreal”.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/march-for-science-crowd-2020-11-20.jpg&quot; alt=&quot;March for Science on Facebook: Picture of protest. Image source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;March for Science on Facebook: Picture of
protest. &lt;a href=&quot;https://www.facebook.com/marchforscience/posts/836983043362678&quot;&gt;Image
source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Woodstock&quot;&gt;Woodstock&lt;/a&gt; or
“an Aquarian Exposition: 3 Days of Peace &amp;amp; Music” festival held in
1969 reportedly attracted “over 400,000”, “450,000”, or “500,000” people
depending on the source. Let’s assume that the real number is somewhere
in-between which gets us to somewhere in the neighborhood of 500,000
people.&lt;/p&gt;
&lt;p&gt;There are numerous aerial photos of the Woodstock crowds, some of
which you can find in &lt;a href=&quot;https://www.gettyimages.com/photos/woodstock-and-aerial&quot;&gt;this
image gallery from Getty images&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;section-3&quot;&gt;750,000&lt;/h2&gt;
&lt;p&gt;Off to look at protests again. This time we are looking at Barcelona
where 750,000 Catalan independence supporters are demanding the release
of their leaders according to &lt;a href=&quot;http://www.timealem.com/750000-people-flood-barcelona-demanding-release-of-catalan-leaders_d575.html&quot;&gt;this
article&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/barcelona-protest-2020-11-20.jpg&quot; alt=&quot;750,000 people flood Barcelona demanding release of Catalan leaders. Image source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;750,000 people flood Barcelona demanding
release of Catalan leaders. &lt;a href=&quot;http://www.timealem.com/750000-people-flood-barcelona-demanding-release-of-catalan-leaders_d575.html&quot;&gt;Image
source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The crowd extends past the top of the frame and there’s no chance
this is the entire crowd. But you get the general idea. If you ship a
bug that affects 0.01% of the internet population, then this is a
conservative lower bound of what that angry mob would look like.&lt;/p&gt;
&lt;p&gt;But wait, the &lt;a href=&quot;https://www.guinnessworldrecords.com/news/non-corporate/2018/6/more-than-750-000-people-help-philippines-based-church-achieve-four-new-records-529029&quot;&gt;Guinness
World Record for the largest charity walk/run&lt;/a&gt; is 283,171 people at a
single venue. Have a look at that picture:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people-2/guinness-record-largest-walk-single-venu-2020-11-20.jpg&quot; alt=&quot;Guinness Record for the largest charity walk or run at a single venue is for 283,171 people. Image Source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Guinness Record for the largest charity
walk or run at a single venue is for 283,171 people. &lt;a href=&quot;https://www.guinnessworldrecords.com/news/non-corporate/2018/6/more-than-750-000-people-help-philippines-based-church-achieve-four-new-records-529029&quot;&gt;Image
Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It seems that picture of 750,000 people doesn’t quite capture that
many people because clearly there are more people in the picture that’s
supposed to be 283k people. Which of course goes to show how hard it is
to really capture how massive a crowd 750k makes.&lt;/p&gt;
&lt;p&gt;In an article on Wired that discusses how hard it is to estimate
crowd sizes, they note&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people-2/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every time a ton of people gather in one place, there are all sorts
of pronouncements made about how many folks really showed. The figures
rarely agree; Glenn Beck’s rally on the National Mall this summer
attracted a million people, according to Beck cohort Rep. Michelle
Bachman. CBS News pegged it at more like 87,000.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;and-more&quot;&gt;And More&lt;/h2&gt;
&lt;p&gt;I’m going to give up at this point. Pictures purportedly of around
one million people are mostly parts of crowds that have been estimated
to be that big.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Note that figure 2 indicates that the estimate is 49% of
the population would have internet access in 2017. It’s likely that by
2021 we’d at least have reached 50% based on the sharp growth curve.&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people-2/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.wired.com/2011/02/how-many-people-are-in-tahrir-square-heres-how-to-tell/&quot;&gt;How
Many People Are in Tahrir Square? Here’s How to Tell&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people-2/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Fart Limit</title>
      <link href="https://xn--izc.com/posts/fart-limit/" />
      <updated>2021-06-14T15:30:18Z</updated>
      <id>https://xn--izc.com/posts/fart-limit/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Thanks to &lt;a href=&quot;https://youtu.be/suwg7-y70FQ&quot;&gt;Vsauce&lt;/a&gt; for
bringing this particular issue to our attention. The TL;DR of that video
is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most of the gases in your farts are odorless.&lt;/li&gt;
&lt;li&gt;The one that usually makes things stinky is Hydrogen Sulfide.&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The content of H_2_S in a fart is around 50ppm.&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;One fart can travel around 10 ft/s.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://www.osha.gov/hydrogen-sulfide/hazards&quot;&gt;OSHA&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;H_2_S at a concentration of 50ppm (roughly what you’d get if you
inhaled a fart directly into your lungs) you’d suffer &lt;em&gt;Slight
conjunctivitis (“gas eye”) and respiratory tract irritation after 1
hour. May cause digestive upset and loss of appetite.&lt;/em&gt;&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Any practical dosage would be around 3ppm. At that rate it would be
&lt;em&gt;Odor becomes more offensive at 3-5 ppm. Above 30 ppm, odor described
as sweet or sickeningly sweet.&lt;/em&gt;. The key point here is that around
10 times the usual concentration, a fart won’t stink. Instead it will
smell “sweet.”&lt;/li&gt;
&lt;li&gt;At 100ppm – which is around 30 times the usual dose – you won’t
smell anything at all because you’ll lose your sense of smell
(&lt;em&gt;olfactory fatigue or paralysis&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;At 1000ppm – 300 times the usual dose – it’s &lt;strong&gt;nearly instant
death&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I guess it is in fact possible.&lt;/p&gt;
&lt;p&gt;As an aside, I found it quite disappointing that the
&lt;strong&gt;Listen&lt;/strong&gt; button on the &lt;a href=&quot;https://kidshealth.org/en/kids/fart.html&quot;&gt;“What’s a Fart” page on
KidsHealth.org&lt;/a&gt; doesn’t make a fart sound. I mean, what else was that
button supposed to do?&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/fart-limit/images/kids-health-fart.png&quot; alt=&quot;KidsHealth: What’s a Fart?&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;KidsHealth: What’s a Fart?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;https://web.archive.org/web/20210614200353/https://www.houstonmethodist.org/blog/articles/2020/oct/flatulence-everything-you-wanted-to-know-about-farting/&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;https://www.chemistryworld.com/news/explainer-the-chemistry-of-farts/2500168.article&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;https://www.osha.gov/hydrogen-sulfide/hazards&lt;a href=&quot;https://xn--izc.com/posts/fart-limit/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Shannon Paper</title>
      <link href="https://xn--izc.com/posts/shannon-paper/" />
      <updated>2021-03-26T20:14:20Z</updated>
      <id>https://xn--izc.com/posts/shannon-paper/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Claude Shannon’s &lt;em&gt;A mathematical theory of communication&lt;/em&gt; is
an oft cited classic in information theory. In fact, as of this writing
there are 84’411 citations and 139 versions of the article on Google
Scholar.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/shannon-paper/images/google-scholar-shannon-citations.png&quot; alt=&quot;Screenshot of Google Scholar showing citation count for Shannon’s paper&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Screenshot of Google Scholar showing
citation count for Shannon’s paper&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Let’s dive in and try to tease apart the “why”s that are often
overlooked when people build on top of the introduced theory. They are
definitely things that I didn’t consider to be obvious without the
benefit of reading the paper.&lt;/p&gt;
&lt;p&gt;The section headings below correspond to the sections in Shannon’s
paper.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The paper’s introduction states the purpose as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;… [To] extend [the general theory of communication] to include a
number of new factors, in particular the effect of noise in the channel,
and the savings possible due to the statistical structure of the
original message and due to the nature of the final destination of
information.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The two most salient points from this section are&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;the arguments for a logarithmic measure of information, and&lt;/li&gt;
&lt;li&gt;what a measure of information actually measures.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Logarithmic measures are well suited for measuring information,
Shannon states, because it’s &lt;em&gt;“nearer to our intuitive feeling as to
the proper measure.”&lt;/em&gt; Additional rationalization exists in the
paper, but I found this to be the most convincing.&lt;/p&gt;
&lt;p&gt;To intuit, adding a channel that’s equal in capacity to an existing
channel increases the space of transferrable messages quadratically.
However our intuition finds it easier to think of this as doubling the
capacity. The latter is more in line with a logarithmic measure.&lt;/p&gt;
&lt;p&gt;Information is what’s ultimately useful for the recipient. Hence a
measure of information must be based on the ability gained by the
recipient upon receipt of the message. Receiving a signal means that the
recipient can now uniquely identify a message among a large number of
possible messages, or to reduce the space of possible messages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If the destination receives 10 bits of information, that
means that the recipient is now able to uniquely select a message from
&lt;span class=&quot;math inline&quot;&gt;2^{10}&lt;/span&gt; possible messages.&lt;/strong&gt; Or
equivalently, the recipient can choose one out of &lt;span class=&quot;math inline&quot;&gt;2^{10}&lt;/span&gt; outcomes.&lt;/p&gt;
&lt;p&gt;Hence the measure of information is based on the ratio of the space
of possible messages before and after receipt of the information.&lt;/p&gt;
&lt;p&gt;The following sections focus on defining and measuring the space of
messages.&lt;/p&gt;
&lt;h2 id=&quot;part-i-discrete-noiseless-systems&quot;&gt;Part I: Discrete Noiseless
Systems&lt;/h2&gt;
&lt;p&gt;A discrete noiseless channel is one in which a selection of symbols
from a finite alphabet can be transmitted from a source to a destination
without loss. It’s not necessarily the case that each symbol consumes an
equal amount of resources to send. Since the paper pertains to
electronic communication Shannon states the cost in terms of time.&lt;/p&gt;
&lt;h3 id=&quot;discrete-noiseless-channel&quot;&gt;1. Discrete Noiseless Channel&lt;/h3&gt;
&lt;p&gt;Capacity of a channel is defined to be the maximum amount of
information that can be transferred over that channel.&lt;/p&gt;
&lt;p&gt;The capacity &lt;span class=&quot;math inline&quot;&gt;C&lt;/span&gt; of a discrete
noiseless channel is defined to be:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;C = &#92;lim_{T &#92;to &#92;infty} &#92;frac{&#92;log
N(T)}{T}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here &lt;span class=&quot;math inline&quot;&gt;N(T)&lt;/span&gt; is the number of allowed
messages that take a duration of &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt; to
transmit. Let’s see how this comes about.&lt;/p&gt;
&lt;p&gt;From the prior definition of information, if the recipient receives
&lt;span class=&quot;math inline&quot;&gt;C&lt;/span&gt; bits of information that means that
they were able to distinguish between &lt;span class=&quot;math inline&quot;&gt;2^C&lt;/span&gt; possible messages.&lt;/p&gt;
&lt;p&gt;So we start with counting the number of possible messages that
could’ve been transmitted over &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt; time.
If we denote this count as &lt;span class=&quot;math inline&quot;&gt;N(T)&lt;/span&gt;, then
we know that there were &lt;span class=&quot;math inline&quot;&gt;&#92;log{N(T)}&lt;/span&gt; bits
of information transferred during &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt;
time. Hence the rate is:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;R(T) = &#92;frac{&#92;log{N(T)}}{T}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To generalize, we find the limit of &lt;span class=&quot;math inline&quot;&gt;R(T)&lt;/span&gt; as &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt;
tends to &lt;span class=&quot;math inline&quot;&gt;&#92;infty&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Suppose the channel can transmit &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;
symbols &lt;span class=&quot;math inline&quot;&gt;{S_1, S_2, ..., S_n}&lt;/span&gt; each of
which consume &lt;span class=&quot;math inline&quot;&gt;{t_1, t_2, ..., t_n}&lt;/span&gt;
units of time. How many possible messages can there be in &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt; units of time? I.e. what’s &lt;span class=&quot;math inline&quot;&gt;N(T)&lt;/span&gt;?&lt;/p&gt;
&lt;p&gt;To break this down a bit further, we can ask &lt;em&gt;“how many possible
messages could there be that end in &lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt;
during time period &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt;?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Any message that ends in &lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt; can be
written as a message consisting of arbitrary symbols &lt;span class=&quot;math inline&quot;&gt;s_1 s_2 ... s_k&lt;/span&gt; (where each &lt;span class=&quot;math inline&quot;&gt;s_i &#92;in S&lt;/span&gt;) and ending with the symbol &lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt;. I.e.:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;underbrace{&#92;underbrace{s_1 s_2 s_3 ...
s_k}_{T - t_i &#92;text{ seconds}} S_i}_{T &#92;text{ seconds}}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As shown, the length of the &lt;span class=&quot;math inline&quot;&gt;s_1..s_k&lt;/span&gt;
portion in time must be &lt;span class=&quot;math inline&quot;&gt;T - t_i&lt;/span&gt; since
the remaining &lt;span class=&quot;math inline&quot;&gt;t_i&lt;/span&gt; time is consumed by
&lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Hence there can be &lt;span class=&quot;math inline&quot;&gt;N(T - t_i)&lt;/span&gt;
possibilities for the &lt;span class=&quot;math inline&quot;&gt;s_1 ... s_k&lt;/span&gt;
prefix.&lt;/p&gt;
&lt;p&gt;Thus we can state this problem recursively as follows:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;N(T) = N(T - t_1) + N(T - t_2) + ... + N(T
- t_n)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;… where &lt;span class=&quot;math inline&quot;&gt;N(T) = 0&lt;/span&gt; for all &lt;span class=&quot;math inline&quot;&gt;T &#92;lt &#92;min(t_1, t_2, ... t_n)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Solving this equation involves recognizing that this is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Linear_difference_equation&quot;&gt;linear
difference equation&lt;/a&gt; (not to be confused with a linear
&lt;em&gt;differential&lt;/em&gt; equation).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If all &lt;span class=&quot;math inline&quot;&gt;t_i&lt;/span&gt; are
distinct&lt;/strong&gt;, then the characteristic polynomial corresponding to
this recurrence is:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;X^{-t_1} + X^{-t_2} + ... + X^{-t_n} =
1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If &lt;span class=&quot;math inline&quot;&gt;X_0&lt;/span&gt; is the largest real solution
to the characteristic equation, then &lt;span class=&quot;math inline&quot;&gt;N(T)&lt;/span&gt; approaches &lt;span class=&quot;math inline&quot;&gt;X_0^T&lt;/span&gt; for large &lt;span class=&quot;math inline&quot;&gt;T&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;(I need to check the math here since Shannon just says this is a well
known result and moves on.)&lt;/p&gt;
&lt;p&gt;So now we have:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;C = &#92;lim_{T &#92;to &#92;infty} &#92;frac{&#92;log
N(T)}{T} = &#92;log X_0&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-discrete-source-of-information&quot;&gt;2. The Discrete Source of
information&lt;/h3&gt;
&lt;p&gt;This section of the paper focuses on defining what at discrete source
of information is. For our purposes it can be thought of as a stochastic
process which produces a stream of symbols.&lt;/p&gt;
&lt;h3 id=&quot;discrete-approximations-to-english&quot;&gt;3. Discrete Approximations
to English&lt;/h3&gt;
&lt;p&gt;Here we come to word and sentence generation using stochastic
processes. In particular Shannon takes us through the progression of
constructing messages via:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Zero-order approximation. Symbols are individual letters with the
addition of a space. Each symbol is selected with equal
probability.&lt;/li&gt;
&lt;li&gt;First-order approximation. As above, but the relative frequencies
correspond to actual letter frequencies in English.&lt;/li&gt;
&lt;li&gt;Second-order approximation. As above, but selection of a symbol
depends on the previous symbol. I.e. follows a digram structure.
Probabilities correspond to English.&lt;/li&gt;
&lt;li&gt;Third-order approximation. As above, but using trigrams instead of
digrams.&lt;/li&gt;
&lt;li&gt;First-order word approximation. Start with a list of words and pick
them at random with probability corresponding to their usage in
English.&lt;/li&gt;
&lt;li&gt;Second-order word approximation. As above, but selection frequencies
depend on the previous word. I.e. follows digrams.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By the time we arrive at second-order word approximations, the
generated messages start to resemble natural English albeit
nonsensical.&lt;/p&gt;
&lt;h3 id=&quot;graphical-representation-of-a-markoff-process&quot;&gt;4. Graphical
Representation of a Markoff process&lt;/h3&gt;
&lt;p&gt;Identifies the previous stochastic processes as Markoff processes.
They are represented as a set of states. Each state can
probabilistically transition to number of states with some probability
distribution. Each transition emits a symbol.&lt;/p&gt;
&lt;p&gt;If the emitted symbol doesn’t depend on any prior symbol, then we
only really need one state. It will have a self-edge for each possible
emitted symbol.&lt;/p&gt;
&lt;pre class=&quot;graphviz&quot;&gt;&lt;code&gt;digraph {
  nodesep=1.5;
  S -&amp;gt; S [label=&amp;quot;0.2&#92;n&#92;n &amp;#39;A&amp;#39;&amp;quot;];
  S -&amp;gt; S [label=&amp;quot;0.2&#92;n &#92;n&amp;#39;B&amp;#39;&amp;quot;];
  S -&amp;gt; S [label=&amp;quot;0.6&#92;n &#92;n&amp;#39;C&amp;#39;&amp;quot;];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the emitted symbol depends on the previous symbol, then there will
be as many states needed as there are symbols. This is the case for
digrams.&lt;/p&gt;
&lt;pre class=&quot;graphviz&quot;&gt;&lt;code&gt;digraph {
  A -&amp;gt; A [label=&amp;quot;0.33, A&amp;quot;];
  A -&amp;gt; B [label=&amp;quot;0.33, B&amp;quot;];
  A -&amp;gt; C [label=&amp;quot;0.33, C&amp;quot;];
  B -&amp;gt; A [label=&amp;quot;0.33, A&amp;quot;];
  B -&amp;gt; B [label=&amp;quot;0.33, B&amp;quot;];
  B -&amp;gt; C [label=&amp;quot;0.33, C&amp;quot;];
  C -&amp;gt; A [label=&amp;quot;0.33, A&amp;quot;];
  C -&amp;gt; B [label=&amp;quot;0.33, B&amp;quot;];
  C -&amp;gt; C [label=&amp;quot;0.33, C&amp;quot;];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For trigrams, since they depend on the previous two symbols, require
&lt;span class=&quot;math inline&quot;&gt;n^2&lt;/span&gt; states.&lt;/p&gt;
&lt;h3 id=&quot;ergodic-and-mixed-sources&quot;&gt;5. Ergodic and Mixed Sources&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;In an ergodic process every sequence produced by the process is the
same in statistical properties. […] Roughly the ergodic property means
statistical homogeneity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;choice-uncertainty-and-entropy&quot;&gt;6. Choice Uncertainty and
Entropy&lt;/h3&gt;
&lt;p&gt;Here we come to the part that is most often cited. The definition of
entropy.&lt;/p&gt;
&lt;p&gt;Shannon lays out three requirements for a measure of information
&lt;span class=&quot;math inline&quot;&gt;H(p_1, p_2, .. p_n)&lt;/span&gt; which measures the
information content of a set of outcomes each of whose probability is
&lt;span class=&quot;math inline&quot;&gt;p_i&lt;/span&gt;:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt; should be continuous in the &lt;span class=&quot;math inline&quot;&gt;p_i&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;If all &lt;span class=&quot;math inline&quot;&gt;p_i&lt;/span&gt; are equal, i.e. &lt;span class=&quot;math inline&quot;&gt;p_i = &#92;frac{1}{n}&lt;/span&gt; then &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt; should be a monotonic increasing function
of &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;If a choice be broken down into two choices, then the original &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt; should be the weighted sum of the
individual values of &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The only &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt; satisfying the above
three requirements is of the form: &lt;span class=&quot;math display&quot;&gt;H = -K
&#92;sum_{i=1}^n p_i &#92;log p_i&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The constant &lt;span class=&quot;math inline&quot;&gt;K&lt;/span&gt; is merely a unit of
measure and can be set to 1.&lt;/p&gt;
&lt;p&gt;Some interesting properties of &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt;:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;span class=&quot;math inline&quot;&gt;H = 0&lt;/span&gt; only when all but one &lt;span class=&quot;math inline&quot;&gt;p_i = 0&lt;/span&gt;, and the remaining &lt;span class=&quot;math inline&quot;&gt;p_j = 1&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;For a given &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;, the maximum &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt; is reached when all &lt;span class=&quot;math inline&quot;&gt;p_i = &#92;frac{1}{n}&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;The joint entropy of two random variables follow the relation: &lt;span class=&quot;math display&quot;&gt;H(x,y) &#92;le H(x) + H(y)&lt;/span&gt; The condition of
equality implies that &lt;span class=&quot;math inline&quot;&gt;x&lt;/span&gt; and &lt;span class=&quot;math inline&quot;&gt;y&lt;/span&gt; are independent.&lt;/li&gt;
&lt;li&gt;Any change towards equalization of probabilities &lt;span class=&quot;math inline&quot;&gt;p_i&lt;/span&gt; increases &lt;span class=&quot;math inline&quot;&gt;H&lt;/span&gt;. I.e. if &lt;span class=&quot;math inline&quot;&gt;p_1 &#92;lt
p_2&lt;/span&gt; and &lt;span class=&quot;math inline&quot;&gt;&#92;delta &#92;lt |p_1 - p_2|&lt;/span&gt;,
then the entropy of &lt;span class=&quot;math inline&quot;&gt;p_1, p_2, ... p_n&lt;/span&gt;
is lower than the entropy of &lt;span class=&quot;math inline&quot;&gt;(p_1 + &#92;delta),
(p_2 - &#92;delta), p_3, ... p_n&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;For two variables &lt;span class=&quot;math inline&quot;&gt;x,y&lt;/span&gt;,there’s
conditional probability &lt;span class=&quot;math inline&quot;&gt;p_i(j)&lt;/span&gt; of &lt;span class=&quot;math inline&quot;&gt;y&lt;/span&gt; having value &lt;span class=&quot;math inline&quot;&gt;j&lt;/span&gt; assuming &lt;span class=&quot;math inline&quot;&gt;x&lt;/span&gt;
has value &lt;span class=&quot;math inline&quot;&gt;i&lt;/span&gt;. This is given by: &lt;span class=&quot;math display&quot;&gt;p_i(j) = &#92;frac{p(i,j)}{&#92;sum_j p(i,j)}&lt;/span&gt; The
corresponding conditional entropy &lt;span class=&quot;math inline&quot;&gt;H_x(y)&lt;/span&gt; is given by: &lt;span class=&quot;math display&quot;&gt;H_x(y) = - &#92;sum_{i,j} p(i,j) &#92;log p_i(j)&lt;/span&gt;
This conditional entropy then holds the relation: &lt;span class=&quot;math display&quot;&gt;H(x,y) = H(x) + H_x(y)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;From 3 and 5, we have: &lt;span class=&quot;math display&quot;&gt;H(y) &#92;le
H_x(y)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;the-entropy-of-an-information-source&quot;&gt;7. The Entropy of an
Information Source&lt;/h3&gt;
&lt;p&gt;Let &lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt; be a set of states each of
which produce some set of outputs &lt;span class=&quot;math inline&quot;&gt;s_j&lt;/span&gt;
with probability &lt;span class=&quot;math inline&quot;&gt;p_{i,j}&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Each state &lt;span class=&quot;math inline&quot;&gt;S_i&lt;/span&gt; has an associated
entropy &lt;span class=&quot;math inline&quot;&gt;H_i&lt;/span&gt; representing the entropy of
all possible outputs from that state. I.e.:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;H_i = - &#92;sum_j p_{i,j} &#92;log
p_{i,j}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Each such state also has a probability of occurrence &lt;span class=&quot;math inline&quot;&gt;P_i&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The entropy of the entire information source is the weighted sum of
the state-wise entropies. The weight being the probability of
occurrence. Thus:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;begin{align*}
H &amp;amp; = &#92;sum_i P_i H_i &#92;&#92;
  &amp;amp; = - &#92;sum_{i,j} P_i p_{i,j} &#92;log p_{i,j}
&#92;end{align*}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If the source is operating at some definite time rate, then the
&lt;strong&gt;entropy per second&lt;/strong&gt;, or &lt;strong&gt;entropy rate&lt;/strong&gt; is
&lt;em&gt;defined&lt;/em&gt; to be:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;H&amp;#39; = &#92;sum_i f_i H_i&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&quot;math inline&quot;&gt;f_i&lt;/span&gt; is the average frequency
of state &lt;span class=&quot;math inline&quot;&gt;i&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Shannon says “Clearly &lt;span class=&quot;math inline&quot;&gt;H&amp;#39; = mH&lt;/span&gt;
where &lt;span class=&quot;math inline&quot;&gt;m&lt;/span&gt; is the average number of
symbols produced per second.” But in order to make the connection you
need to observe that &lt;span class=&quot;math inline&quot;&gt;f_i = m &#92;cdot
P_i&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;This is followed by a derivation that takes some work to follow.
Let’s go through it step by step:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Suppose that the information source consists of a single state
and &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt; symbols each of which is emitted
with a probability of &lt;span class=&quot;math inline&quot;&gt;p_i&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now take a string of length &lt;span class=&quot;math inline&quot;&gt;N&lt;/span&gt;
emitted by this source. The expected number of occurrences for symbol
&lt;span class=&quot;math inline&quot;&gt;s_i&lt;/span&gt; is &lt;span class=&quot;math inline&quot;&gt;N
p_i&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A message of sufficient length where all symbols appear at their
expected occurrence count would have a probability of occurring of:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;p = &#92;prod_i p_i^{N p_i}&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From there we see that:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;begin{align*}
&#92;log p &amp;amp; = &#92;sum_i N p_i &#92;log p_i &#92;&#92;
       &amp;amp; = N H
&#92;end{align*}&lt;/span&gt;&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Sometimes It&#39;s the Interviewers Who Suck</title>
      <link href="https://xn--izc.com/posts/sometimes-its-the-interviewers-who-suck/" />
      <updated>2021-03-20T23:09:49Z</updated>
      <id>https://xn--izc.com/posts/sometimes-its-the-interviewers-who-suck/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;I’ve done hundreds of interviews. I’ve also served in numerous hiring
committees over the years.&lt;/p&gt;
&lt;p&gt;Tech companies tend to have cultures built around tech people
interviewing other tech people, typically in what is
not-so-affectionately known as the “Tech interview.” This is good
because candidates would be evaluated based on their actual skills
instead of keywords in their resume. Interviewers are in effect choosing
their future coworkers which makes the interview serve the interest of
both the interviewer and the interviewee. However candidates – at least
the one who didn’t get accepted according to exit polls – tend to hate
this interview format.&lt;/p&gt;
&lt;p&gt;The goal of the tech interview is to assess how well the candidate
will be able to perform in the role as a tech worker. Unfortunately the
typical problems that one would encounter during the course of a career
in tech aren’t easy to replicate within a 40-60 minute interview. So
partly the criticism is around the fact that such interviews bear little
resemblance to what the actual job would entail. Deciphering what
happens during an interview and distilling it into a prediction of
future success is quite difficult in the best of times.&lt;/p&gt;
&lt;p&gt;Making this much worse is the undeniable fact that many if not most
&lt;em&gt;tech workers are just not good interviewers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is as true as a claim that most tech workers aren’t good
managers – whether it’s managing projects or people. Interview follow-up
don’t take this factor into consideration quite as much as they
should.&lt;/p&gt;
&lt;p&gt;My anecdotal evidence is that when presented with the artifacts from
a bad interview, hiring committees will disproportionately blame the
candidate for it. After all if the candidate was really good, they
would’ve potentially salvaged the interview. The problem
disproportionately affects candidates who are near the middle of the
skill curve where things can probably go one way or the other depending
on the combination of question asked, and caliber of the
interviewer.&lt;/p&gt;
&lt;p&gt;Interviews at Google famously involve a bunch of paperwork where each
interviewer is expected to produce some verbose artifacts detailing what
happened. Since these artifacts come from the interviewer, hiring
committees need to exercise some due diligence to discern what actually
happened based on the writeup. So how do we go about spotting bad
interviews?&lt;/p&gt;
&lt;h3 id=&quot;the-writeup-is-terse.&quot;&gt;The writeup is terse.&lt;/h3&gt;
&lt;p&gt;Not in and of itself a conclusive sign, but if the writeup doesn’t
have any details that a committee could use to form a decision, it’s
likely a sign that the interview didn’t really gather much information
about the candidate in the first place. Typically these kinds of
writeups are from novice interviewers who don’t know what to write
about.&lt;/p&gt;
&lt;h3 id=&quot;the-writeup-uses-adversarial-framing.&quot;&gt;The writeup uses
adversarial framing.&lt;/h3&gt;
&lt;p&gt;A very frequent problem specially with novice interviewers is that
they go into the interview thinking that it is some sort of competition
between the interviewer and the interviewee. The interviewer might
consider it a &lt;em&gt;bad&lt;/em&gt; thing if a candidate were to hit their
question out of the park. Some of this comes from a certain level of
imposter syndrome where they don’t want to come across as less smart
than the candidate. Either way this mentality comes across during the
interview as hostile or condescending.&lt;/p&gt;
&lt;h3 id=&quot;the-interviewer-takes-too-much-pleasure-in-the-interviewees-misery.&quot;&gt;The
interviewer takes too much pleasure in the interviewee’s misery.&lt;/h3&gt;
&lt;p&gt;Each mistake is gloated on while points at which the interviewee
obviously shone are muted.&lt;/p&gt;
&lt;h3 id=&quot;the-question-is-unnecessarily-hard.&quot;&gt;The question is
unnecessarily hard.&lt;/h3&gt;
&lt;p&gt;Solving a hard question that requires a great deal of time and
thought is very satisfying. But it isn’t what you do on a day-to-day
basis.&lt;/p&gt;
&lt;h3 id=&quot;the-interviewer-allows-the-interviewee-to-march-into-the-weeds-without-helping-them-back.&quot;&gt;The
interviewer allows the interviewee to march into the weeds without
helping them back.&lt;/h3&gt;
&lt;p&gt;The interviewer has the luxury of having seen the question beforehand
and also having studied possible solutions to it. They should be
familiar enough with the question that they could spot
misunderstandings, misconceptions, and common mistakes. How a candidate
notices a misstep and how they dig themselves out is important to note.
However, letting the candidate languish in a dead-end while the clock
ticks away the remaining minutes of an interview does not help
anyone.&lt;/p&gt;
&lt;h3 id=&quot;obvious-misunderstandings-are-not-corrected.&quot;&gt;Obvious
misunderstandings are not corrected.&lt;/h3&gt;
&lt;p&gt;It is the interviewer’s responsibility to explain the problem
clearly. The problem itself doesn’t need to be fully explained since
there’s much value in seeing how a candidate explores and understands
the problem area. However if it is obvious that the candidate has
fundamentally misunderstood some critical aspect of the question, the
interviewer should step in and intervene &lt;strong&gt;early&lt;/strong&gt;. We all
misunderstand things, specially when they aren’t clearly explained. It’s
not useful to knowingly send a candidate down the wrong path.&lt;/p&gt;
&lt;h3 id=&quot;the-interviewer-seemed-annoyed-or-angry.&quot;&gt;The interviewer seemed
annoyed or angry.&lt;/h3&gt;
&lt;p&gt;This one should be self explanatory. The candidate is anxious enough
as it is. The interviewer should not frustrate the interviewee’s
attempts at asking questions and seeking clarity around the question.
It’s likely that while the problem is obvious to one, the problem area
may be unfamiliar to others who may need extra help figuring their way
around. In fact the ability to resolve such ambiguities and seek clarity
are &lt;em&gt;good&lt;/em&gt;. If the interviewer actively discourages such inquiry
that’s on the interviewer – not the candidate.&lt;/p&gt;
&lt;h3 id=&quot;one-interview-diverges-significantly-from-others.&quot;&gt;One interview
diverges significantly from others.&lt;/h3&gt;
&lt;p&gt;There’s more than one interview for a reason. If one interview
highlights an area as being weak while another interview highlights the
same area as being strong, then there’s something going on that needs
scrutiny. There can be many reasons why a candidate bombs an interview.
Not all of them say anything bad about their ability to function well in
their job. The causes should be teased out.&lt;/p&gt;
&lt;p&gt;–&lt;/p&gt;
&lt;p&gt;What happens when an interview is pretty much unsalvageable? It might
be that the writeup is inconclusive due to issues such as those
highlighted above. A committee could ignore that specific interview and
base their decision on the other interviews, or failing that schedule
another interview to account for the lack of decisive information.&lt;/p&gt;
&lt;p&gt;From a candidate’s point of view, it is &lt;strong&gt;really&lt;/strong&gt;
important that they report any unpleasant interactions to one’s
recruiter immediately after the interview. This allows a recruiter to go
to bat for you and perhaps get you another interview if appropriate.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>On WontFixing Bugs</title>
      <link href="https://xn--izc.com/posts/on-wontfixing-bugs/" />
      <updated>2021-03-02T22:15:06Z</updated>
      <id>https://xn--izc.com/posts/on-wontfixing-bugs/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;This was partly inspired by a Tweet by a co-worker. The tweet is:&lt;/p&gt;
&lt;p&gt;https://twitter.com/miketaylr/status/1366762904851279877”&lt;/p&gt;
&lt;p&gt;For projects that are under-resourced but has heavy usage it is in
fact quite normal to accumulate a large number of issue reports over
time. Take Chromium for example. There are (at the time of writing)
~95,000 open bugs. Many of these are task tracking bugs rather than
tracking actual product bugs. But still that’s a lot of real bugs.&lt;/p&gt;
&lt;p&gt;What’s even more interesting is the accumulation of bugs. Typically
for a “successful” project the rate of new issues being reported will
exceed the rate of issues being fixed. Hence the growth.&lt;/p&gt;
&lt;h2 id=&quot;what-matters&quot;&gt;What Matters …&lt;/h2&gt;
&lt;p&gt;Issues are often annotated to indicate some measure of
&lt;em&gt;severity&lt;/em&gt; and &lt;em&gt;priority&lt;/em&gt;. These are two different axes of
measurement:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt; refers to the degree of impact that an
issue has. How many users are affected? Is the effect isolated or spread
across a large user base? Severity is supposed to summarize the answer
to these questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Priority&lt;/strong&gt; refers to what the issue triagers deemed to
be the relative importance of the issue. A bug that affects a large
number of users – hence a high severity – might not be a high priority
due to mitigating factors. Typically a project owner would tackle higher
priority issues first. Under-resourced projects – which is the case for
pretty much every successful project I’ve seen – will accumulate lower
priority issues across time.&lt;/p&gt;
&lt;p&gt;Neither &lt;em&gt;severity&lt;/em&gt; nor &lt;em&gt;priority&lt;/em&gt; are static either. An
issue with a low severity might be elevated to a higher severity if the
affected population of users is discovered to be larger than originally
assumed. Or the priority may be raised if the issue is blocking the fix
for another more severe issue. It’s not uncommon for some low priority
issue to be suddenly elevated to critical status once someone figures
out how to exploit it.&lt;/p&gt;
&lt;p&gt;In practice &lt;em&gt;perceptual priority&lt;/em&gt; is the only one that
matters. It doesn’t matter what the issue tracker label or score is.
What matters is that there’s a contributor who’s motivated to fix it.
The decisions of a contributor are complex and subjective. So while the
most important issues will &lt;em&gt;likely&lt;/em&gt; get fixed, just because an
issue is real or important doesn’t mean that it will be addressed.&lt;/p&gt;
&lt;p&gt;What this means is that it is important for issue reports to stick
around. At worst they will accumulate more evidence of severity or clues
to what the issue is. Often the desired outcome isn’t universal either.
So an issue report also functions as an opinion catchment area where
interested parties can hash out their differences.&lt;/p&gt;
&lt;h2 id=&quot;and-what-doesnt&quot;&gt;And What Doesn’t …&lt;/h2&gt;
&lt;p&gt;However, the health of the project then depends on not only handling
new issues, but also in how they shepherd existing or known issues.&lt;/p&gt;
&lt;p&gt;Much like any other todo list, the effectiveness of the issue tracker
decreases when there’s an overwhelming number of items to look at. The
cognitive overhead of correct prioritizing increases dramatically, as
does the time it takes for triaging.&lt;/p&gt;
&lt;h2 id=&quot;strategies-that-dont-work&quot;&gt;Strategies That Don’t Work …&lt;/h2&gt;
&lt;p&gt;So projects tend to use various techniques to deal with the growing
pile of issues. The more overwhelming it is, the more drastic the
mitigation strategy.&lt;/p&gt;
&lt;p&gt;One such strategy in action is what we see in the Tweet above where
there’s a bot that automatically closes old issues that haven’t seen any
activity. At first glance this seems to make sense.&lt;/p&gt;
&lt;p&gt;The assumption seems to be that if the issue was important enough
then an endless stream of users would pipe up on the bug with “me too”s
to keep the issue open. The issue tracker is now a battlefield where
issue reporters have to continually work to keep the issue alive until a
contributor takes pity and addresses it.&lt;/p&gt;
&lt;p&gt;Issue reporters themselves who are often volunteers who are electing
to participate in a project can also burn out. If the issues they file
are automatically closed, it’s frustrating to the reporters. Chances are
that with every few issues that are closed due to inactivity, the
project loses a contributor.&lt;/p&gt;
&lt;p&gt;Another strategy is to have new issues start at some sort of
&lt;em&gt;unconfirmed&lt;/em&gt; state. Once the issue has been acknowledged and
accepted it can proceed to some other state which makes the issue become
a candidate for contributor consideration. This one is a bit better in
that it doesn’t discard &lt;em&gt;confirmed&lt;/em&gt; issues.&lt;/p&gt;
&lt;p&gt;However, eventually the real issues will accumulate to the point
where some sort of bookkeeping is needed. Along comes
&lt;code&gt;WontFix&lt;/code&gt; and friends. This is a state where the issue is
marked as &lt;em&gt;“this is a real issue but we will probably never get
around to fixing it.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Reporters nevertheless find this state to be no-less frustrating than
an outright closure. &lt;code&gt;WontFix&lt;/code&gt;ed bugs don’t show up by
default in issue searches, so they are effectively undiscoverable to
future issue reporters. All time invested in that issue is now lost.&lt;/p&gt;
&lt;h2 id=&quot;and-one-that-does&quot;&gt;And One That Does? …&lt;/h2&gt;
&lt;p&gt;The alternative is to just leave the issue open, but lower the
priority down to something that reflects the current opinion of the
project maintainers.&lt;/p&gt;
&lt;p&gt;This strategy acknowledges that the issue is real. It serves as
documentation that the product has a known defect, and in addition it
can serve the purposes of accumulating evidence of severity along the
way. If the issue becomes prominent enough then it can be retriaged.&lt;/p&gt;
&lt;p&gt;That’s it. So far I haven’t seen alternatives that are much better
than this. I’m generally against mass issue closing events like
declaring “bug bankruptcy.” The bugs don’t care about the state of the
issue report. All you’ve accomplished is to throw away the accumulated
history and evidence of a defect.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Deriving the Poisson Distribution</title>
      <link href="https://xn--izc.com/posts/poisson-distribution/" />
      <updated>2020-12-11T16:13:39Z</updated>
      <id>https://xn--izc.com/posts/poisson-distribution/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Where does the Poisson Distribution come from?&lt;/p&gt;
&lt;p&gt;A little bit of research&lt;a href=&quot;https://xn--izc.com/posts/poisson-distribution/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; tells us that the
distribution was originally introduced by &lt;a href=&quot;https://en.wikipedia.org/wiki/Abraham_de_Moivre&quot;&gt;Abraham de
Moivre&lt;/a&gt; in 1710 in an article called &lt;em&gt;“On the Measurement of
Chance, or, on the Probability of Events in Games Depending Upon
Fortuitous Chance”&lt;/em&gt; &lt;a href=&quot;https://xn--izc.com/posts/poisson-distribution/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; (not the original title).&lt;/p&gt;
&lt;p&gt;A few steps that will get us there is laid out below.&lt;/p&gt;
&lt;p&gt;Let’s start with a simple “rate” problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How likely is it that you’ll receive 12 visits next week given that
you had 10 visitors this week?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is clearly not a question to be answered based on a lot of
information. However when the assumption is that &lt;em&gt;on average&lt;/em&gt; you
get 10 visitors a week, then the question sounds a bit more
reasonable.&lt;/p&gt;
&lt;p&gt;While we say the &lt;em&gt;rate&lt;/em&gt; is 10 visitors per week, that’s
obviously not going to be uniformly distributed. Maybe given the nature
of your site, people are more likely to visit over the week-end rather
than during the week. However for the purpose of this analysis we are
going to assume that the rate is uniform.&lt;/p&gt;
&lt;p&gt;Simplifying things a bit more, we can ask the question in a different
way:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How likely is that that the rate of visitors for your site will be
&lt;span class=&quot;math inline&quot;&gt;&#92;frac{12}{7}&lt;/span&gt; per day next week given
that the usual rate is &lt;span class=&quot;math inline&quot;&gt;&#92;frac{10}{7}&lt;/span&gt; per
day?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or in another way:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How likely is that that the rate of visitors for your site will be
&lt;span class=&quot;math inline&quot;&gt;&#92;frac{12}{7 * 24}&lt;/span&gt; per hour next week
given that the usual rate is &lt;span class=&quot;math inline&quot;&gt;&#92;frac{10}{7 *
24}&lt;/span&gt; per hour?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why do this? Without much explanation this reformulation gets us to a
rate that’s less than one per unit of time being considered. This way we
can now look at each time unit and assume that we’ll either get 1
visitor or none any given hour.&lt;/p&gt;
&lt;p&gt;So each hour, there’s a probability of &lt;span class=&quot;math inline&quot;&gt;&#92;lambda&lt;/span&gt; that there will be a user, and &lt;span class=&quot;math inline&quot;&gt;1 - &#92;lambda&lt;/span&gt; that there won’t. Here we are
using &lt;span class=&quot;math inline&quot;&gt;&#92;lambda = &#92;frac{10}{7 * 24}&lt;/span&gt; for
convenience. The latter is also the “rate” of events or arrivals. The
term &lt;em&gt;arrivals&lt;/em&gt; or &lt;em&gt;occurrences&lt;/em&gt; is common in
literature.&lt;/p&gt;
&lt;p&gt;The probability that there will be 12 visitors is the probability
that there will be 12 hour slots where there’s an arrival and the rest
will be slots without an arrival.&lt;/p&gt;
&lt;p&gt;Treating this as a list of one-hour “slots”, the outcome would look
like:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;th&gt;…&lt;/th&gt;
&lt;th&gt;0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The number in each box is the number of arrivals during that slot
which is either 1 or 0. So there are &lt;span class=&quot;math inline&quot;&gt;2^n&lt;/span&gt; possible outcomes where &lt;span class=&quot;math inline&quot;&gt;n = 7 * 24&lt;/span&gt;. Each 1 has a probability of &lt;span class=&quot;math inline&quot;&gt;&#92;lambda&lt;/span&gt; and 0 has a probability of &lt;span class=&quot;math inline&quot;&gt;1 - &#92;lambda&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So for there to be exactly &lt;span class=&quot;math inline&quot;&gt;k&lt;/span&gt;
arrivals – where &lt;span class=&quot;math inline&quot;&gt;k = 12&lt;/span&gt; which is the
target – there needs to be &lt;span class=&quot;math inline&quot;&gt;k&lt;/span&gt; ones and
&lt;span class=&quot;math inline&quot;&gt;n - k&lt;/span&gt; zeros.&lt;/p&gt;
&lt;p&gt;So the probability of one of those events happening is &lt;span class=&quot;math inline&quot;&gt;&#92;lambda^k (1 - &#92;lambda)^{n-k}&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;But there are lots of ways of choosing &lt;span class=&quot;math inline&quot;&gt;k&lt;/span&gt; boxes out of &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;. In fact there is exactly &lt;span class=&quot;math inline&quot;&gt;&#92;binom{n}{k}&lt;/span&gt; ways.&lt;/p&gt;
&lt;p&gt;So the probability of getting exactly &lt;span class=&quot;math inline&quot;&gt;k&lt;/span&gt; arrivals is:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;Pr(k) = &#92;binom{n}{k} &#92;lambda^k
(1-&#92;lambda)^{n - k}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With me so far?&lt;/p&gt;
&lt;p&gt;Astute readers will note that we did some hand-waving up there.
Specifically we assumed that the possibilities for any 1-hour block is
either there being an arrival or there not being one. This isn’t always
the case since there could be more than 1 arrival in any given hour.&lt;/p&gt;
&lt;p&gt;One way to address this is to consider increasingly smaller units of
time. For example, if we divide the one-hour block into &lt;span class=&quot;math inline&quot;&gt;m&lt;/span&gt; equal sized pieces then it’ll be a bit more
likely – assuming &lt;span class=&quot;math inline&quot;&gt;m &#92;gt 1&lt;/span&gt; – that there
will be at most 1 arrival during that time period. In fact if &lt;span class=&quot;math inline&quot;&gt;m&lt;/span&gt; is very large, then it is increasingly
likely that the choices are either 1 or 0.&lt;/p&gt;
&lt;p&gt;So the number of boxes is now &lt;span class=&quot;math inline&quot;&gt;n*m&lt;/span&gt;,
and the probability of an arrival during any single timeslot is now
&lt;span class=&quot;math inline&quot;&gt;&#92;frac{λ}{m}&lt;/span&gt;. Substituting these, our
new probability is:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;Pr(k) = &#92;binom{nm}{k} &#92;left(
&#92;frac{&#92;lambda}{m} &#92;right)^k &#92;left(1 - &#92;frac{&#92;lambda}{m}&#92;right)^{nm -
k}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Alright. We are getting somewhere now. The next step is to increase
&lt;span class=&quot;math inline&quot;&gt;m&lt;/span&gt; all the way to &lt;span class=&quot;math inline&quot;&gt;&#92;infty&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;begin{align*}
&#92;lim_{m &#92;to &#92;infty} &#92;Pr(k) &amp;amp; = &#92;lim_{m &#92;to &#92;infty} &#92;binom{n*m}{k} (
&#92;frac{λ}{m} )^k (1 - &#92;frac{λ}{m})^{nm - k} &#92;&#92;
&amp;amp; = &#92;lim_{m → &#92;infty} &#92;frac{(nm)!}{k! (nm - k)!} ( &#92;frac{λ}{m} )^k
(1 - &#92;frac{λ}{m})^{nm - k}
&#92;end{align*}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The right side looks a bit daunting, the we can simplify things quite
a bit by looking at each part separately.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;begin{align*}
&#92;binom{nm}{k}&#92;left( &#92;frac{&#92;lambda}{m} &#92;right)^k  &amp;amp; = &#92;frac{(nm)!}{k!
(nm - k)!}&#92;left( &#92;frac{&#92;lambda}{m} &#92;right)^k &#92;&#92;
&amp;amp; = &#92;frac{nm &#92;cdot (nm - 1) &#92;cdot (nm - 2) &#92;cdot ... (nm - k +
1)}{k!}&#92;left( &#92;frac{&#92;lambda}{m} &#92;right)^k &#92;&#92;
&amp;amp; = &#92;left( &#92;frac{nm}{m} &#92;right) &#92;left( &#92;frac{nm  - 1}{m}&#92;right) ...
&#92;left( &#92;frac{nm - k + 1}{m}&#92;right) &#92;frac{&#92;lambda^k}{k!}
&#92;end{align*}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Furthermore:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;left( &#92;frac{nm}{m} &#92;right) &#92;left(
&#92;frac{nm  - 1}{m}&#92;right) ... &#92;left( &#92;frac{nm - k + 1}{m}&#92;right)
&#92;frac{&#92;lambda^k}{k!} = &#92;frac{&#92;lambda^k}{k!}&#92;prod_{i=0}^{k-1} &#92;left(n -
&#92;frac{k - i}{m}&#92;right)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As &lt;span class=&quot;math inline&quot;&gt;&#92;lim_{m → &#92;infty}&lt;/span&gt; we see that
&lt;span class=&quot;math inline&quot;&gt;&#92;frac{k-i}{m}&lt;/span&gt; tends to &lt;span class=&quot;math inline&quot;&gt;0&lt;/span&gt;. This makes our lives a bit easier.&lt;/p&gt;
&lt;p&gt;Now we have:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;begin{align*}
&#92;Pr(k) &amp;amp;= &#92;lim_{m &#92;to &#92;infty}&#92;frac{(n &#92;lambda)^k}{k!} &#92;left(1 -
&#92;frac{&#92;lambda}{m} &#92;right)^{nm - k} &#92;&#92;
&amp;amp;= &#92;lim_{m &#92;to &#92;infty}&#92;frac{(n &#92;lambda)^k}{k!} &#92;left(1 -
&#92;frac{&#92;lambda}{m} &#92;right)^{nm(1 - &#92;frac{k}{nm})}&#92;end{align*}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Remember that:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;lim_{n &#92;to &#92;infty} &#92;left( 1 + &#92;frac{x}{n}
&#92;right)^n = e^x&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So substituting &lt;span class=&quot;math inline&quot;&gt;n &#92;to nm&lt;/span&gt; and &lt;span class=&quot;math inline&quot;&gt;x &#92;to - &#92;lambda n&lt;/span&gt; gets us:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;lim_{nm &#92;to &#92;infty} &#92;left( 1 -
&#92;frac{&#92;lambda}{m} &#92;right)^{nm} = e^{- &#92;lambda n}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now going back to &lt;span class=&quot;math inline&quot;&gt;&#92;Pr(k)&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;Pr(k) = &#92;frac{(n &#92;lambda)^k e^{- &#92;lambda
n}}{k!} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s do another substitution. Remember that &lt;span class=&quot;math inline&quot;&gt;&#92;lambda&lt;/span&gt; is the number of arrivals during
&lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt; time periods. If we consider &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt; time periods (originally hours) to be a
single unit of time, then our rate of arrivals is &lt;span class=&quot;math inline&quot;&gt;&#92;lambda n&lt;/span&gt;. So without loss of generality
let’s substitute &lt;span class=&quot;math inline&quot;&gt;&#92;lambda n &#92;to
&#92;lambda&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;This gives us:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math display&quot;&gt;&#92;Pr(k) = &#92;frac{&#92;lambda^k e^{-
&#92;lambda}}{k!}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;… which is the PDF of the Poisson distribution.&lt;/p&gt;
&lt;p&gt;n.b.: In retrospect it would’ve been easier to consider the unit of
time to be &lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt; hours in the first place,
but I’m too lazy to go back and rewrite everything.&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Also known as reading the relevant Wikipedia article. In
this case that’s the &lt;a href=&quot;https://en.wikipedia.org/wiki/Poisson_distribution#History&quot;&gt;&lt;em&gt;History&lt;/em&gt;
section of the article on the Poisson distribution&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/posts/poisson-distribution/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://royalsocietypublishing.org/doi/10.1098/rstl.1710.0018&quot;&gt;The
original article in Latin&lt;/a&gt; is available via &lt;a href=&quot;https://royalsociety.org/journals/&quot;&gt;The Royal Society
Publishing&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/posts/poisson-distribution/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Ten Years</title>
      <link href="https://xn--izc.com/posts/ten-years/" />
      <updated>2020-12-09T02:41:50Z</updated>
      <id>https://xn--izc.com/posts/ten-years/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;It’s been ten years since I started at Google. The work anniversary
fell on 6th of December.&lt;/p&gt;
&lt;p&gt;Ten years ago my wife and I made our way to Mountain View for my
orientation; all excited for a brand new chapter in our lives. After
spending a week in Mountain View / Palo Alto we both decided that
California was not for us. But that’s beside the point.&lt;/p&gt;
&lt;p&gt;I was elated. This was pretty much everything I dreamt of as a kid
growing up in Sri Lanka. Except those days we dreamt of someday working
for Microsoft or starting our own software company.&lt;/p&gt;
&lt;p&gt;One afternoon during orientation – maybe it was the evening, I don’t
remember – I was walking by a bunch of outdoor tables next to one of the
larger café’s at the Google HQ. As I walked by I overheard a Googler on
the phone telling someone how they just had a really shitty day. I
remember being confused. How could someone have a bad day at Google?
Inconceivable.&lt;/p&gt;
&lt;p&gt;Obviously this feeling didn’t last. People normalize things quickly.
The problem with achieving your dreams is that now you have to make
more; an eternal treadmill. It’s nice to periodically look back though.
The novelty isn’t there anymore, but it’s humbling to recall how much we
dreamt for the things that we now take for granted.&lt;/p&gt;
&lt;p&gt;Looking back at the last years, the things that I’m really proud of
aren’t my code contributions. If any aren’t already obsolete then by now
it’s become some legacy crap that some engineer has to maintain.&lt;/p&gt;
&lt;p&gt;But the things that I really remember are the three times I talked
hiring committees into hiring someone they had decided not to hire.
Those were good candidates whom I thought didn’t get a fair shake.&lt;/p&gt;
&lt;p&gt;Also I clearly remember the smart people who acknowledged and
appreciated my work. I also remember the ones that took credit for my
work or didn’t treat me with dignity, but I don’t think about them that
often.&lt;/p&gt;
&lt;p&gt;I remember the big projects that I initiated, the big ideas I sold,
and the ones I managed to pull off.&lt;/p&gt;
&lt;p&gt;Then there are the low points. Moments when I let people down or
burned a bridge or two for the wrong reasons.&lt;/p&gt;
&lt;p&gt;But overall, looking back there isn’t much there. It’s surprising how
little really matters in the long run.&lt;/p&gt;
&lt;p&gt;I should remember that the next time I feel like staying up late
trying to get something done because I feel some sort of obligation or
bigger purpose in doing it. Often there is none.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Visualizing Internet Users</title>
      <link href="https://xn--izc.com/posts/visualizing-people/" />
      <updated>2020-11-21T16:37:53Z</updated>
      <id>https://xn--izc.com/posts/visualizing-people/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;What does 0.3%&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; of internet users look like?&lt;/p&gt;
&lt;p&gt;As of this writing the global population hovers around 7.7 billion
according to the World Population Clock &lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/census-gov-population-clock-2020-11-20.png&quot; alt=&quot;Screenshot from census.gov showing the world population clock.&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Screenshot from census.gov showing the
world population clock.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.itu.int/&quot;&gt;International Telecommunications
Union&lt;/a&gt; “estimates that at the end of 2019, 53.6 per cent of the
global population, or 4.1 billion people, are using the internet.”&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/itu-internet-usage-stats-2019.jpg&quot; alt=&quot;Screenshot from itu.int showing historical internet usage numbers as a percentage of the world population&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Screenshot from itu.int showing
historical internet usage numbers as a percentage of the world
population&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So a 0.3% of the internet would be a roughly 12,300,000 or around
12.3 million. A nice little number.&lt;/p&gt;
&lt;h2 id=&quot;from-50-to-100000&quot;&gt;From 50 to 100,000&lt;/h2&gt;
&lt;p&gt;It’s interesting to try and visualize this. An example of visualizing
populations for small numbers can be found at &lt;a href=&quot;https://blog.lime.link/visualizing-crowd-sizes/&quot;&gt;Visualizing Crowd
Sizes&lt;/a&gt;. It goes from around 50 people up to 100,000 people.&lt;/p&gt;
&lt;p&gt;While 100,000 is interesting we need to go all the way to 12.3
million.&lt;/p&gt;
&lt;h2 id=&quot;section&quot;&gt;200,000&lt;/h2&gt;
&lt;p&gt;A particularly macabre topic these days since the United States
surpassed 200,000 deaths due to COVID-19 around September of 2020. &lt;a href=&quot;https://www.ctpost.com/&quot;&gt;ctpost&lt;/a&gt; ran an article online title &lt;a href=&quot;https://www.ctpost.com/news/coronavirus/slideshow/Analysis-What-200-000-COVID-deaths-actually-209169.php&quot;&gt;“What
does 200,000 deaths actually look like”&lt;/a&gt;. There are some interesting
comparisons there, but none make for a good visual. It’s just an
interesting number right now.&lt;/p&gt;
&lt;p&gt;As for crowd sizes, 200,000 was the estimated number of people who
attended the &lt;a href=&quot;https://marchforourlives.com/&quot;&gt;March for Our
Lives&lt;/a&gt; in D.C.. There aren’t any photos capturing &lt;em&gt;all&lt;/em&gt;
attendees in one shot, but there are numerous pictures in &lt;a href=&quot;https://www.cbsnews.com/news/march-for-our-lives-crowd-size-estimated-200000-people-attended-d-c-march/&quot;&gt;this
CBS News article&lt;/a&gt; to give you a good idea.&lt;/p&gt;
&lt;p&gt;In more terrible examples, &lt;a href=&quot;https://www.dw.com/en/more-than-200000-indonesians-protest-governor-purnamas-alleged-blasphemy/a-36611145&quot;&gt;this
article on dw.com&lt;/a&gt; suggests that the crowd size pictured is roughly
around 200,000 people.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;More than 200,000 conservative Muslims gathered in Indonesia’s
capital Jakarta on Friday to protest against the city’s Christian
governor, who is facing trial for blasphemy, police estimated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/dw-com-indonesia-protest-2020-11-20.jpg&quot; alt=&quot;Image from dw.com of a protest in Indonesia allegedly showing 200,000 people. Image Source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Image from dw.com of a protest in
Indonesia allegedly showing 200,000 people. &lt;a href=&quot;https://www.dw.com/en/more-than-200000-indonesians-protest-governor-purnamas-alleged-blasphemy/a-36611145&quot;&gt;Image
Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;section-1&quot;&gt;500,000&lt;/h2&gt;
&lt;p&gt;We are heading into shaky ground here. A 800*600 picture only
contains 480,000 pixels. So we are now reduced to indicating population
by inference. It is nolonger possible to capture 500,000 people in a
webpage sized picture while showing each person individually.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.reddit.com/r/philadelphia/comments/3by9g8/if_this_is_what_500k_people_look_like_xpost_from/&quot;&gt;This
Reddit post&lt;/a&gt; claims that there are 500k people in the picture, but I
couldn’t readily find any good references backing up that claim.&lt;/p&gt;
&lt;p&gt;As is tradition by now, another protest that drew 500,000 people is
&lt;a href=&quot;https://www.nbcnews.com/show-me/video/nearly-500-000-people-march-in-anti-violence-rally-in-barcelona-1033617987741&quot;&gt;an
anti-violence rally in Barcelona as reported by NBC&lt;/a&gt;. While there’s
video, the content doesn’t quite capture the massive number of people.
Also it’s “nearly 500,000” people.&lt;/p&gt;
&lt;p&gt;However, the closest we’ll probably get to a somewhat believable
500,000 person crowd would be the March for Science. They posted the
following picture on &lt;a href=&quot;https://www.facebook.com/marchforscience/posts/836983043362678&quot;&gt;Facebook&lt;/a&gt;
noting that “There are 500,000 people on strike in Montreal”.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/march-for-science-crowd-2020-11-20.jpg&quot; alt=&quot;March for Science on Facebook: Picture of protest&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;March for Science on Facebook: Picture of
protest&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.facebook.com/marchforscience/posts/836983043362678&quot;&gt;Image
source&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;section-2&quot;&gt;750,000&lt;/h2&gt;
&lt;p&gt;Off to protests again. This time we are looking at Barcelona where
750,000 Catalan independence supporters are demanding the release of
their leaders according to &lt;a href=&quot;http://www.timealem.com/750000-people-flood-barcelona-demanding-release-of-catalan-leaders_d575.html&quot;&gt;this
article&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/barcelona-protest-2020-11-20.jpg&quot; alt=&quot;750,000 people flood Barcelona demanding release of Catalan leaders. Image source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;750,000 people flood Barcelona demanding
release of Catalan leaders. &lt;a href=&quot;http://www.timealem.com/750000-people-flood-barcelona-demanding-release-of-catalan-leaders_d575.html&quot;&gt;Image
source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The crowd extends past the top of the frame and there’s no chance
this is the entire crowd. But you get the general idea. If you ship a
bug that affects 0.01% of the internet population, then this is a
conservative lower bound of what that angry mob would look like.&lt;/p&gt;
&lt;p&gt;But wait, the &lt;a href=&quot;https://www.guinnessworldrecords.com/news/non-corporate/2018/6/more-than-750-000-people-help-philippines-based-church-achieve-four-new-records-529029&quot;&gt;Guinness
World Record for teh largest charity walk/run&lt;/a&gt; is 283,171 people at a
single venue. Have a look at that picture:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/visualizing-people/guinness-record-largest-walk-single-venu-2020-11-20.jpg&quot; alt=&quot;Guinness Record for the largest charity walk or run at a single venue is for 283,171 people. Image Source&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Guinness Record for the largest charity
walk or run at a single venue is for 283,171 people. &lt;a href=&quot;https://www.guinnessworldrecords.com/news/non-corporate/2018/6/more-than-750-000-people-help-philippines-based-church-achieve-four-new-records-529029&quot;&gt;Image
Source&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It seems that picture of 750,000 people doesn’t quite capture it
because clearly there are more people in the picture that’s supposed to
be 283k people. Which of course goes to show how hard it is to really
capture how massive a crowd 750k makes.&lt;/p&gt;
&lt;p&gt;In an article on Wired that discusses how hard it is to estimate
crowd sizes, they note&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fn4&quot; class=&quot;footnote-ref&quot; id=&quot;fnref4&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every time a ton of people gather in one place, there are all sorts
of pronouncements made about how many folks really showed. The figures
rarely agree; Glenn Beck’s rally on the National Mall this summer
attracted a million people, according to Beck cohort Rep. Michelle
Bachman. CBS News pegged it at more like 87,000.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;and-more&quot;&gt;And More&lt;/h3&gt;
&lt;p&gt;I’m going to give up at this point. Pictures purportedly of around
one million people are mostly parts of crowds that have been estimated
to be that big. Forget about 12.3 million.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Why 0.3% of the internet population? It’s a number that
came up when trying to come up with a reasonable sample size for
estimating the diversity of the internet population. There’s not much
special about it other than that.&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;The &lt;a href=&quot;https://www.census.gov/popclock/&quot;&gt;world
population clock&lt;/a&gt;. This link is for the current number at whatever
time you clicked on the link assuming the site is still there. As of
November 20, 2021, the number was 7.7 billion. I’d link you to an
archived page but that doesn’t seem to work.&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.itu.int/en/ITU-D/Statistics/Pages/stat/default.aspx&quot;&gt;Statistics
pages on itu.int&lt;/a&gt; project even higher numbers than 53.6% by the end
of 2020, but it’s possible numbers won’t behave according to historical
trends due to the effects of COVID.&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn4&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.wired.com/2011/02/how-many-people-are-in-tahrir-square-heres-how-to-tell/&quot;&gt;How
Many People Are in Tahrir Square? Here’s How to Tell&lt;/a&gt;&lt;a href=&quot;https://xn--izc.com/posts/visualizing-people/#fnref4&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Things You Can Do With Neovim and Vscode That You Can&#39;t Do With Neovim Alone</title>
      <link href="https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/" />
      <updated>2020-09-19T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;This is the third time I’ve tried in earnest to switch to VSCode from
Vim (or Neovim in my case) for reasons not all of which are relevant to
this post. But I love Vim style modal editing and I’ve grown accustomed
to some features that aren’t present or not well emulated in &lt;a href=&quot;https://github.com/VSCodeVim/Vim&quot;&gt;VSCodeVim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/asvetliakov/vscode-neovim&quot;&gt;VSCode
Neovim&lt;/a&gt;. I was intrigued by their claim to integrate Neovim instead
of trying to emulate Vim. After going through the code a bit I thought
this extension alone warranted a new attempt at switching to VSCode. So
far it’s going great.&lt;/p&gt;
&lt;h2 id=&quot;how-vscode-neovim-works&quot;&gt;How VSCode Neovim Works&lt;/h2&gt;
&lt;p&gt;Here’s the gist of how this extension works. Feel free to skip to the
good stuff below but this section is good background information for
understanding &lt;em&gt;why&lt;/em&gt; it works the way it does.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invokes an embedded Neovim instance.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Code for this is in the &lt;code&gt;main_controller.ts&lt;/code&gt; (&lt;a href=&quot;https://github.com/asvetliakov/vscode-neovim/blob/master/src/main_controller.ts&quot;&gt;linky&lt;/a&gt;)
if you are curious about how exactly it’s implemented and the
commandline options that are passed in.&lt;/p&gt;
&lt;p&gt;You’ll also notice that the code invokes
&lt;code&gt;--cmd source ${neovimSupportScriptPath}&lt;/code&gt; which runs
&lt;code&gt;vim/vscode-neovim.vim&lt;/code&gt; (&lt;a href=&quot;https://github.com/asvetliakov/vscode-neovim/blob/master/vim/vscode-neovim.vim&quot;&gt;linky&lt;/a&gt;)
before running your &lt;code&gt;init.vim&lt;/code&gt; file. This script is what sets
up the &lt;code&gt;g:vscode&lt;/code&gt; flag and sources all the other
&lt;code&gt;vscode-*.vim&lt;/code&gt; scripts except
&lt;code&gt;vscode-options.vim&lt;/code&gt;. The latter runs &lt;em&gt;after&lt;/em&gt; your
&lt;code&gt;init.vim&lt;/code&gt; in order to force some settings that would
otherwise break the extension or cause Neovim to be confused.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So far this is pretty standard fare for how Neovim would be embedded
for a custom UI. But things get a bit interesting from the next
step.&lt;/p&gt;
&lt;ol start=&quot;2&quot; type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creates a new Neovim buffer and window corresponding to a
VSCode editor.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The buffer thus created is a plain text buffer without any bells or
whistles. Contents of the buffer comes from VSCode&lt;a href=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.
VSCodeNeovim synchronizes the content between the Neovim buffer and the
VSCode editor. Thus the relationship between the contents and the
corresponding file on disk is mediated through VSCode. This is a key
difference between other custom UIs and this one and one that opens many
possibilities.&lt;/p&gt;
&lt;p&gt;VSCodeNeovim defers to VSCode for handling insert mode. VSCode
handles autocompletion and other assistive features. You’ll have to get
used to your insert mode customizations not working, or replicating that
with VSCode keyboard mapping customizations. When exiting insert mode
the extension asynchronously synchronizes the buffer contents – which at
this point would include the changes that were introduced – with Neovim.
The code for synchronizing the VSCode editor contents and the Neovim
buffer is in &lt;code&gt;buffer_manager.ts&lt;/code&gt; (&lt;a href=&quot;https://github.com/asvetliakov/vscode-neovim/blob/master/src/buffer_manager.ts&quot;&gt;linky&lt;/a&gt;)
which is also a good place to look if you want to know the details about
buffer options that are being set.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course I’m eliding lots of detail here including integrations for
other areas of UI. But I think this captures the pertinent details. The
extension is a pretty impressive piece of work which is well worth a
gander. Now on to the good stuff.&lt;/p&gt;
&lt;h2 id=&quot;responsive-neovim-experience-over-a-laggy-ssh-connection&quot;&gt;Responsive
Neovim Experience Over A laggy SSH Connection&lt;/h2&gt;
&lt;p&gt;This gets to the reason why I’m trying to move to VSCode in the first
place. I work on a project consisting of thousands of C++ source files.
My home-office doesn’t have enough hardware to do regular builds, or in
fact any build at all. The beefy machines are in a remote location
accessible via SSH.&lt;/p&gt;
&lt;p&gt;I’ve been using Neovim over SSH for a while, but the latency really
bothers me. And no, neither SCP nor SSHFS scratches this itch because I
won’t have access to language smarts like &lt;code&gt;clangd&lt;/code&gt; which
require access to all the source files and some build tooling.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/remote/remote-overview&quot;&gt;VSCode
Remote Development&lt;/a&gt; was a nearly perfect answer with the exception
that VSCodeVim didn’t quite have all the functionality I needed.
VSCodeNeovim addresses that last piece of the puzzle.&lt;/p&gt;
&lt;p&gt;VSCode + Remote SSH + VSCodeNeovim + Neovim gives me:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/architecture.png&quot; alt=&quot;Architecture of VSCode + Remote SSH + VSCodeNeovim + Neovim&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Architecture of VSCode + Remote SSH +
VSCodeNeovim + Neovim&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;On the remote machine:
&lt;ul&gt;
&lt;li&gt;Source files.&lt;/li&gt;
&lt;li&gt;Build tooling.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clangd&lt;/code&gt; process invoked via
&lt;code&gt;vscode-remote&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;On the local machine:
&lt;ul&gt;
&lt;li&gt;VSCode.&lt;/li&gt;
&lt;li&gt;VSCodeNeovim.
&lt;ul&gt;
&lt;li&gt;Neovim instance embedded by VSCodeNeovim.
&lt;ul&gt;
&lt;li&gt;Neovim plug-ins and normal mode keybindings.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the embedded Neovim instance is local the editors are super
responsive. Completions via &lt;code&gt;clangd&lt;/code&gt; is still laggy as one
might expect. But that’s something I’m willing to live with.&lt;/p&gt;
&lt;h2 id=&quot;proportional-fonts-with-neovim&quot;&gt;Proportional Fonts With
Neovim&lt;/h2&gt;
&lt;p&gt;Okay, so why would anyone actually want this? Turns out &lt;a href=&quot;https://www.google.com/search?q=proportional+fonts+for+coding&quot;&gt;I’m
not the only one&lt;/a&gt;. In my case I prefer monospace for regular code,
but I’d much much rather read comments and prose in proportional font.
Also, I now spend a lot of my time writing Markdown with LatexMath.
Staring at monospaced prose all day is not my cup of tea.&lt;/p&gt;
&lt;p&gt;This is what it looks like when I’m editing this post in VSCode (in
Markdown).&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/proportional-font-markdown.png&quot; alt=&quot;Screenshot of VSCode editing Markdown in proportional font&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Screenshot of VSCode editing Markdown in
proportional font&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The best part is that I can use my familiar Vim/Neovim keybindings
and modal editing. I had to make a couple of customizations and I only
have this set up for Markdown. But it works fairly well. One gotcha is
that the cursor jumps horizontally when moving the cursor up or down
since the columns are no longer neatly aligned.&lt;/p&gt;
&lt;h3 id=&quot;monospace-code-with-proportional-comments&quot;&gt;Monospace Code With
Proportional Comments?&lt;/h3&gt;
&lt;p&gt;What I really want isn’t proportional fonts everywhere. Rather I only
want proportional fonts for prose. In code, this would take the form of
comments.&lt;/p&gt;
&lt;p&gt;Unfortunately, VSCode doesn’t support changing the font for specific
syntactic tokens or scopes. That would’ve been ideal because it would
let me configure things so that comments are in proportional font while
the rest is in monospace. Also in the case of Markdown, I’d be able to
make everything proportional except for inline code and fenced code
blocks. Alas we are not quite there yet. Several feature requests
already exist&lt;a href=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;, but hasn’t seen much activity.&lt;/p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;VSCodeNeovim is a functional replacement for the avid Neovim or
perhaps Vim user who wants it both ways. Lots of caveats exist including
the fact that Neovim mode only really works inside editor windows.&lt;/li&gt;
&lt;li&gt;VSCodeNeovim + “Remote SSH” is an awesome combination for editing
remote files using Neovim with the latency of a local Neovim
instance.&lt;/li&gt;
&lt;li&gt;You can use proportional fonts with VSCodeNeovim for super double
awesomeness.&lt;/li&gt;
&lt;/ol&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Not quite the whole story because it’s possible a buffer
be created inside the Neovim instance and have it be mirrored in a
VSCode editor. But that’s probably not what you’ll be using on a regular
basis.&lt;a href=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;A quick search in the VSCode repository &lt;a href=&quot;https://github.com/microsoft/vscode/search?q=tokenColorCustomizations+font+name&quot;&gt;with
this query&lt;/a&gt; yields several issues that request for pretty much the
same thing: Allow setting &lt;code&gt;fontName&lt;/code&gt; in
&lt;code&gt;tokenColorCustomizations&lt;/code&gt;. There’s also &lt;a href=&quot;https://github.com/deepanrajkumar/Italic-and-Ligature&quot;&gt;this
curious experiment&lt;/a&gt; which patches in a different font for italics so
that you can use the existing &lt;code&gt;fontStyle: &quot;italic&quot;&lt;/code&gt; option in
&lt;code&gt;tokenColorCustomizations&lt;/code&gt; to switch fonts.&lt;a href=&quot;https://xn--izc.com/posts/things-you-can-do-with-nvim-and-vscode/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Why &#39;Strong Opinions Weakly Held&#39;</title>
      <link href="https://xn--izc.com/posts/why-strong-opinions-weakly-held/" />
      <updated>2020-08-28T19:17:16Z</updated>
      <id>https://xn--izc.com/posts/why-strong-opinions-weakly-held/</id>
      <content xml:lang="en" type="html">
        &lt;h2 id=&quot;origins-of-the-phrase&quot;&gt;Origins of the phrase&lt;/h2&gt;
&lt;p&gt;The title of this blog is &lt;strong&gt;Strong Opinions, Weakly
Held&lt;/strong&gt;. The same concept shows up elsewhere are &lt;em&gt;Strong
Opinions Loosely Held&lt;/em&gt;. An eponymous essay by Paul Saffo in &lt;span class=&quot;citation&quot; data-cites=&quot;Saffo&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/why-strong-opinions-weakly-held/#ref-Saffo&quot; role=&quot;doc-biblioref&quot;&gt;2020&lt;/a&gt;)&lt;/span&gt; introduced the world to this
concept.&lt;/p&gt;
&lt;p&gt;In his essay – which isn’t very long if you would like to &lt;a href=&quot;https://www.saffo.com/02008/07/26/strong-opinions-weakly-held/&quot;&gt;read
the whole thing yourself&lt;/a&gt; – he lays out the concept as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have found that the fastest way to an effective forecast is often
through a sequence of lousy forecasts. Instead of withholding judgment
until an exhaustive search for data is complete, I will force myself to
make a tentative forecast based on the information available, and then
systematically tear it apart, using the insights gained to guide my
search for further indicators and information.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;criticism&quot;&gt;Criticism&lt;/h2&gt;
&lt;p&gt;Cedric Chin’s critique &lt;span class=&quot;citation&quot; data-cites=&quot;Cedric&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/why-strong-opinions-weakly-held/#ref-Cedric&quot; role=&quot;doc-biblioref&quot;&gt;2020&lt;/a&gt;)&lt;/span&gt; comes down to
two points that the author summarizes as follows:&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;In my experience, ‘strong opinions, weakly held’ is difficult to put
into practice. Most people who try will either:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Use it as downside-protection to justify their strongly-held bad
opinions, or&lt;/li&gt;
&lt;li&gt;Struggle to shift from one strong opinion to another.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The reason it is difficult is because it works against the grain of
the human mind.&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;So don’t bother. The next time you find yourself making a judgment,
don’t invoke ‘strong opinions, weakly held’. Instead, ask: “how much are
you willing to bet on that?” Doing so will jolt people into the types of
thinking you want to encourage.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Michael Natkin on &lt;span class=&quot;citation&quot; data-cites=&quot;Michael&quot;&gt;(&lt;a href=&quot;https://xn--izc.com/posts/why-strong-opinions-weakly-held/#ref-Michael&quot; role=&quot;doc-biblioref&quot;&gt;2020&lt;/a&gt;)&lt;/span&gt; points out the
fallacy of assuming that strong opinions will be reliably
challenged:&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;The idea of strong opinions, loosely held is that you can make
bombastic statements, and everyone should implicitly assume that you’ll
happily change your mind in a heartbeat if new data suggests you are
wrong. It is supposed to lead to a collegial, competitive environment in
which ideas get a vigorous defense, the best of them survive, and no-one
gets their feelings hurt in the process.&lt;/p&gt;
&lt;p&gt;[…]&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;What really happens? The loudest, most bombastic engineer states
their case with certainty, and that shuts down discussion. Other people
either assume the loudmouth knows best, or don’t want to stick out their
neck and risk criticism and shame. This is especially true if the
loudmouth is senior, or there is any other power differential.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;reconciliation&quot;&gt;Reconciliation&lt;/h2&gt;
&lt;p&gt;Both cases above illustrate the damage caused by the disconnect
between the holder of the opinion and others about the degree of
confidence with which the opinion is held. A strongly held – and thusly
communicated – opinion has a higher chance of being misinterpreted as
conviction.&lt;/p&gt;
&lt;p&gt;Saffo’s original claim still holds that having a potentially
inaccurate position is &lt;em&gt;better than having none at all&lt;/em&gt;. Such a
position elicits arguments and opens up avenues for investigation that
wouldn’t otherwise materialize in the absence of any other catalyst.&lt;/p&gt;
&lt;p&gt;Cedric Chin’s essay points out a simple fix, where the holder of the
opinion also states the degree of confidence. This is meant to dress up
the opinion more as a target than a decree, thus inviting debate instead
of suppressing. I believe this to be good advice.&lt;/p&gt;
&lt;p&gt;Back in my college days, I remember a particularly engaging professor
asking a question like “is claim &lt;em&gt;A&lt;/em&gt; true or is claim &lt;em&gt;B&lt;/em&gt;
true?” After observing a lackluster show of hands he remarked that of
the three groups of students – those that chose &lt;em&gt;A&lt;/em&gt;, those that
chose &lt;em&gt;B&lt;/em&gt;, and those that chose neither – the group that will
leave the lecture having learned the most is the group that gets the
answer wrong. He advised all of us to “get some skin in the game,” even
if you don’t know the answer.&lt;/p&gt;
&lt;p&gt;There is some truth to this. Of course a corporate meeting where we
need to elicit debate from a group of people with varying levels of
confidence is a very different venue than a group of students answering
a question. But a similar principle still applies. The goals might be
different, but it’s still better to cajole everyone to get some skin in
the game instead of not passive silence.&lt;/p&gt;
&lt;h2 id=&quot;what-strong-opinions-weakly-held-means-to-me&quot;&gt;What ‘Strong
Opinions Weakly Held’ Means To Me&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Having an opinion is better than not having one. Accmulation of
raw data is great, but it’s even better when you intentionally accrete
them into something meaningful. Any interpretation of information beyond
establishment of fact is probably going to be in the realm of
opinion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An opinion expressed is better than one that is not as long as
it’s open for criticism. You wouldn’t find out if you were wrong if you
didn’t tell anyone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That it is weakly held is as important to communicate as the
opinion itself. Doing so invites criticism and discussion instead of
suppressing them.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 class=&quot;unnumbered&quot; id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;div id=&quot;refs&quot; class=&quot;references csl-bib-body hanging-indent&quot; data-entry-spacing=&quot;0&quot; data-line-spacing=&quot;2&quot; role=&quot;list&quot;&gt;
&lt;div id=&quot;ref-Michael&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
&lt;em&gt;Strong opinions loosely held might be the worst idea in tech - the
glowforge blog&lt;/em&gt;. (2020, September 4). &lt;a href=&quot;https://blog.glowforge.com/strong-opinions-loosely-held-might-be-the-worst-idea-in-tech/&quot;&gt;https://blog.glowforge.com/strong-opinions-loosely-held-might-be-the-worst-idea-in-tech/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-Saffo&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
&lt;em&gt;Strong opinions weakly held : Paul saffo&lt;/em&gt;. (2020, September 4).
&lt;a href=&quot;https://www.saffo.com/02008/07/26/strong-opinions-weakly-held/&quot;&gt;https://www.saffo.com/02008/07/26/strong-opinions-weakly-held/&lt;/a&gt;
&lt;/div&gt;
&lt;div id=&quot;ref-Cedric&quot; class=&quot;csl-entry&quot; role=&quot;listitem&quot;&gt;
&lt;em&gt;&lt;span&gt;“Strong opinions, weakly held”&lt;/span&gt; doesn’t work that
well&lt;/em&gt;. (2020, September 4). &lt;a href=&quot;https://commoncog.com/blog/strong-opinions-weakly-held-is-bad/&quot;&gt;https://commoncog.com/blog/strong-opinions-weakly-held-is-bad/&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;

      </content>
    </entry>
    <entry>
      <title>Names for Name Conventions</title>
      <link href="https://xn--izc.com/posts/symbol-name-types/" />
      <updated>2020-08-24T16:32:45Z</updated>
      <id>https://xn--izc.com/posts/symbol-name-types/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;Names I’ve seen used to refer to naming conventions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;snake_case&lt;/code&gt;, &lt;code&gt;hacker_case&lt;/code&gt;,
&lt;code&gt;unix_hacker_style&lt;/code&gt; : Everything is lower case, though
exceptions exist. E.g. &lt;code&gt;HTTP_foo_bar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SCREAMING_SNAKE_CASE&lt;/code&gt; : Usually reserved for macros and
constants.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;camelCase&lt;/code&gt; : The first letter is lowercase.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PascalCase&lt;/code&gt; : The first letter is uppercase.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kabob-case&lt;/code&gt; : Like &lt;code&gt;snake_case&lt;/code&gt;, but uses
dashes instead of underscores. Common for command-line options&lt;a href=&quot;https://xn--izc.com/posts/symbol-name-types/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;, CSS styles, commands (e.g.
&lt;code&gt;git-receive-pack&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While looking idly looking for details on this, I stumbled on &lt;a href=&quot;https://medium.com/better-programming/string-case-styles-camel-pascal-snake-and-kebab-case-981407998841&quot;&gt;this
Medium post&lt;/a&gt; which is relevant.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Opinions vary on whether the correct convention for
command line options is &lt;code&gt;snake_case&lt;/code&gt; or
&lt;code&gt;kabob-case&lt;/code&gt;. Long form options are often written as
&lt;code&gt;--long-option&lt;/code&gt;, but can also be &lt;code&gt;--long_option&lt;/code&gt;
(where the delimiter within the option is &lt;code&gt;_&lt;/code&gt;).&lt;a href=&quot;https://xn--izc.com/posts/symbol-name-types/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>How This Blog Works</title>
      <link href="https://xn--izc.com/posts/how-this-blog-works/" />
      <updated>2020-07-27T04:57:17Z</updated>
      <id>https://xn--izc.com/posts/how-this-blog-works/</id>
      <content xml:lang="en" type="html">
        &lt;h1 id=&quot;requirements&quot;&gt;Requirements&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Math. Preferably Latex.&lt;/li&gt;
&lt;li&gt;Citations. I like to cite stuff.&lt;/li&gt;
&lt;li&gt;Figures and pictures and references to thereof.&lt;/li&gt;
&lt;li&gt;Be able to export to Github Flavored Markdown.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;the-stack&quot;&gt;The Stack&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All documents are in Markdown. Specifically &lt;a href=&quot;https://pandoc.org/MANUAL.html&quot;&gt;Pandoc Markdown&lt;/a&gt;. Obviously,
the source is processed via &lt;code&gt;pandoc&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The site itself is compiled using &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The current version (as of this writing) doesn’t support any
configuration when using Pandoc for markup processing. By default Hugo
only passes the &lt;code&gt;--mathjax&lt;/code&gt; option to the &lt;code&gt;pandoc&lt;/code&gt;
invocation. So I had to make some local modifications so that I can
specify filters and some other options to support citations and
references.&lt;/p&gt;
&lt;p&gt;Pull request is &lt;a href=&quot;https://github.com/gohugoio/hugo/pull/7529&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hugo output – which is a static HTML site – gets pushed out to a
separate private GitHub repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt; monitors this
separate GitHub repository and updates this blog.&lt;/p&gt;
&lt;p&gt;As a bonus, the generated static content is pushed out to my GitHub
Pages site. So there’s an easier to remember URL than &lt;a href=&quot;https://xn--izc.com/&quot;&gt;https://අ.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secondary sites are fed via Pandoc which converts from Pandoc
Markdown to Github Flavored Markdown.&lt;/p&gt;
&lt;p&gt;Why secondary sites? For various reasons, the primary site for some
of the articles need to be their own GitHub repository. E.g.
https://github.com/asankah/identity-domains .&lt;/p&gt;
&lt;p&gt;For all those sites, the primary source is the blog. That way I can
use Pandoc, use citations, use math etc. and things will “just work”
when publishing to another site that expects GitHub flavored
Markdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
    <entry>
      <title>The Comcast Technician Problem</title>
      <link href="https://xn--izc.com/posts/comcast-technican-problem/" />
      <updated>2020-07-13T17:21:51Z</updated>
      <id>https://xn--izc.com/posts/comcast-technican-problem/</id>
      <content xml:lang="en" type="html">
        &lt;h2 id=&quot;the-story&quot;&gt;The Story&lt;/h2&gt;
&lt;p&gt;As is a rite of passage in these parts, I waited for the Comcast&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; technician to arrive during their
scheduled appointment window. In preparation I had scheduled a day of
working from home.&lt;/p&gt;
&lt;p&gt;As the appointment window unceremoniously came to a close vacillated
over when it would be a reasonable time to call Comcast again to see
what’s going on. That’s when I noticed the technician’s truck pull up
beside our house. They rolled down the window and surveyed the scene for
a brief moment, looked at something inside their truck, rolled up the
window and promptly drove off.&lt;/p&gt;
&lt;p&gt;“That’s it,” I thought. That was the right time to call Comcast.
That’s what I did. After a long wait&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; the friendly service
person on the other end of the line told me that the according to the
technician nobody answered the door. It took some convincing on my part
to establish that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I was there the whole time. Nobody rang the doorbell.&lt;/li&gt;
&lt;li&gt;The doorbell works.&lt;/li&gt;
&lt;li&gt;The technician — assuming that the person who drove by was the
scheduled technician — did drive by, but they didn’t get out of the
vehicle to ring any doorbell.&lt;/li&gt;
&lt;li&gt;My phone didn’t ring, nor does it indicate any missed calls.&lt;/li&gt;
&lt;li&gt;My phone works and has a signal.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They were kind enough to ask the technician to return, but noted that
the appointment window would now be unpredictable due to prior
appointments. Sure.&lt;/p&gt;
&lt;p&gt;Much later that evening, the same technician who drove by earlier
showed up. After they were done, I thanked them for showing up and
mentioned what happened to the original appointment slot. I didn’t
mention anything about seeing the same technician before. After all I
was just happy that I was done with this and didn’t want to cause any
trouble.&lt;/p&gt;
&lt;p&gt;He said that technicians sometimes skip slots when they are running
behind schedule.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Looking at what happened from the perspective of the technician, the
logic behind all this becomes a little clearer.&lt;/p&gt;
&lt;p&gt;You see, had the technician had tried to honor the original
appointment — one which they were already late for — they would’ve been
even more late for the next one. This would continue down the line until
by the end of the day pretty much all of his appointments that afternoon
would’ve registered as &lt;em&gt;late&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Had they skipped one – my appointment as the case turned out – then
they’d potentially be on time for the rest of their appointments. The
one they skipped could later be justified as one where the customer was
not at home or any other reasonable excuses. Even if they were truthful
and were penalized for missing an appointment, it’s likely that they’d
still be better off than being late for so many more appointments.
Either way, the outcome is both better for the technician, and more
importantly, for their supervisor.&lt;/p&gt;
&lt;p&gt;In the books, the two situations look like this:&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 25%&quot; /&gt;
&lt;col style=&quot;width: 31%&quot; /&gt;
&lt;col style=&quot;width: 22%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Technician’s Choice&lt;/th&gt;
&lt;th&gt;Successful appointments&lt;/th&gt;
&lt;th&gt;Late appointments&lt;/th&gt;
&lt;th&gt;“No-show”s &lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Honor all slots&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;g&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;l&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Skip when late&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;g + l - s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class=&quot;math inline&quot;&gt;n + s&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The outcomes depending on the technician’s decision on what to do
with late appointments.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math inline&quot;&gt;g&lt;/span&gt; are the &lt;em&gt;good&lt;/em&gt; slots where
the technician is able to show up during the appointment window. &lt;span class=&quot;math inline&quot;&gt;l&lt;/span&gt; are those where the technician was not
available during the appointment window. In either case some number of
households are not going to be home or not ready for service. Those are
&lt;span class=&quot;math inline&quot;&gt;n&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;When the technician decides to skip late appointments some number –
&lt;span class=&quot;math inline&quot;&gt;s&lt;/span&gt; in the table above – will turn into
additional no-shows. However, skipping these will mean that the
technician can make it to &lt;span class=&quot;math inline&quot;&gt;l-s&lt;/span&gt;
appointments on time.&lt;/p&gt;
&lt;p&gt;Assuming &lt;span class=&quot;math inline&quot;&gt;l-s &amp;gt; 0&lt;/span&gt;, then the
outcome of the &lt;em&gt;skip when late&lt;/em&gt; strategy is strictly better for
the technician’s supervisor. I can’t imagine there being any incentive
for the supervisor to penalize this strategy. So the technician also
gets off scott free.&lt;/p&gt;
&lt;h2 id=&quot;why-this-is-relevant&quot;&gt;Why This Is Relevant&lt;/h2&gt;
&lt;p&gt;It’s easy to harp on Comcast&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fn4&quot; class=&quot;footnote-ref&quot; id=&quot;fnref4&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; and some random lowly
technician. But this incentive pattern is everywhere. Even at Google and
s.&lt;/p&gt;
&lt;p&gt;Every time you measure someone’s success on &lt;em&gt;how well&lt;/em&gt; they
handled a number of issues or cases without taking into account &lt;em&gt;the
cost they incurred&lt;/em&gt; to get there, you are creating a Comcast
Technician problem for your subordinates.&lt;/p&gt;
&lt;h2 id=&quot;but-is-it-bad&quot;&gt;But Is It Bad?&lt;/h2&gt;
&lt;p&gt;Dropping tasks instead of unbounded accretion of delay is sometimes a
better strategy.&lt;/p&gt;
&lt;p&gt;One might even argue that this is the cost of doing business and it
would actually makes sense. One customer’s (or user’s or client’s or
patient’s) convenience doesn’t outweigh the convenience of many
others.&lt;/p&gt;
&lt;p&gt;There could be additional complicating factors involved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What’s the cost of skipping or rescheduling a case? Is the cost
bourne by you? How much of the cost is bourne by the customer?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do you choose which case to skip? It might be that the case
to skip isn’t the one that’s late, but one later down the schedule
that’s much cheaper to reschedule or less damaging to cancel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In either case, be forgiving when you inevitably find yourself as the
one who got the short end of the stick.&lt;/p&gt;
&lt;p&gt;It just might be that all parties involved are rational actors, and
there’s really not a great alternative. Sometimes it’s just life.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.theverge.com/2014/8/19/6004131/comcast-the-worst-company-in-america&quot;&gt;&lt;em&gt;The
Verge&lt;/em&gt;. &lt;em&gt;The worst company in America.&lt;/em&gt;&lt;/a&gt; (Accessed July
13, 2020)&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.urbandictionary.com/define.php?term=Long%20Wait&quot;&gt;&lt;em&gt;Urban
Dictionary&lt;/em&gt;. &lt;em&gt;Long Wait&lt;/em&gt;&lt;/a&gt; (Accessed July 13, 2020)&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;“No-shows” are just going to be rescheduled. It’s not
the end of the world.&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn4&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.theverge.com/2014/8/19/6004131/comcast-the-worst-company-in-america&quot;&gt;&lt;em&gt;The
Verge&lt;/em&gt;. &lt;em&gt;The worst company in America.&lt;/em&gt;&lt;/a&gt; (Accessed July
13, 2020)&lt;a href=&quot;https://xn--izc.com/posts/comcast-technican-problem/#fnref4&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Vim: Use Drop Not Edit, SBuffer Not Buffer</title>
      <link href="https://xn--izc.com/posts/use-drop-not-edit/" />
      <updated>2020-07-07T16:02:20Z</updated>
      <id>https://xn--izc.com/posts/use-drop-not-edit/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;I’m going to assume you are a Vim user.&lt;/p&gt;
&lt;p&gt;Say you have a several windows open in Vim and you want to edit
another file. Using &lt;code&gt;:edit&lt;/code&gt; works if you want to open the
file in the current window unconditionally.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But that’s often not what you want.&lt;/em&gt; If you have the same
file open in another window, then the most efficient and least
disruptive thing to do is to switch to that window.&lt;/p&gt;
&lt;h2 id=&quot;drop&quot;&gt;drop&lt;/h2&gt;
&lt;p&gt;That’s where &lt;code&gt;:drop&lt;/code&gt; comes in. In case you aren’t familiar
with the &lt;code&gt;drop&lt;/code&gt; command, have a look at the help page in your
favorite editor (&lt;code&gt;:help drop&lt;/code&gt;) or &lt;a href=&quot;http://vimdoc.sourceforge.net/htmldoc/windows.html#:drop&quot;&gt;here on
the web&lt;/a&gt;. But the gist of it is that for most people&lt;a href=&quot;https://xn--izc.com/posts/use-drop-not-edit/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;
&lt;code&gt;:drop {file}&lt;/code&gt; will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Switch to the window in which &lt;code&gt;{file}&lt;/code&gt; is already
open.&lt;/li&gt;
&lt;li&gt;Switch the buffer in the current window to &lt;code&gt;{file}&lt;/code&gt;
otherwise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;:drop&lt;/code&gt; command is intended to be used as the “open
buffer” command for automated tooling like source browsers. For example,
you can configure &lt;code&gt;coc-nvim&lt;/code&gt; &lt;a href=&quot;https://github.com/neoclide/coc.nvim&quot;&gt;GitHub&lt;/a&gt; to use
&lt;code&gt;:drop&lt;/code&gt; as the command used for opening a source file by
setting &lt;code&gt;coc.preferences.jumpCommand&lt;/code&gt; to &lt;code&gt;drop&lt;/code&gt;.
See &lt;code&gt;:help coc-configuration&lt;/code&gt; for details on how to set this,
but basically it’s as simple as opening up the configuration using
&lt;code&gt;:CocConfig&lt;/code&gt; and then adding a
&lt;code&gt;&quot;coc.preferences.jumpCommand&quot;: &quot;drop&quot;,&lt;/code&gt; mapping to the
configuration JSON file.&lt;/p&gt;
&lt;h2 id=&quot;switchbuf-or-swb&quot;&gt;switchbuf or swb&lt;/h2&gt;
&lt;p&gt;Or perhaps configuring each plugin is too much work. Enter
&lt;code&gt;switchbuf&lt;/code&gt;. This is a global setting in Vim that controls
how Vim switches between buffers.&lt;/p&gt;
&lt;p&gt;Setting &lt;code&gt;set switchbuf=useopen&lt;/code&gt; has the same effect when
invoking &lt;code&gt;buffer&lt;/code&gt;. Note that using &lt;code&gt;sbuffer&lt;/code&gt;,
&lt;code&gt;sbnext&lt;/code&gt;, or &lt;code&gt;sbrewind&lt;/code&gt; automatically behaves as
if this is the case. I.e. they will use an existing window if one
already has the buffer open.&lt;/p&gt;
&lt;p&gt;Setting &lt;code&gt;set switchbuf=usetab&lt;/code&gt; is similar to the effect of
&lt;code&gt;useopen&lt;/code&gt; except that it will look through windows in other
tabs.&lt;/p&gt;
&lt;p&gt;See &lt;code&gt;:help switchbuf&lt;/code&gt; or &lt;a href=&quot;http://vimdoc.sourceforge.net/htmldoc/options.html#&amp;#39;switchbuf&amp;#39;&quot;&gt;here
on the web&lt;/a&gt; for full details.&lt;/p&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Assuming you have &lt;code&gt;set hidden&lt;/code&gt; that is. See
&lt;code&gt;:help drop&lt;/code&gt; for more details on what happens when the
current buffer cannot be unloaded.&lt;a href=&quot;https://xn--izc.com/posts/use-drop-not-edit/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
    <entry>
      <title>Notes from Crash Course&#39;s Videos on Fact Checking Information You See On The Internet
</title>
      <link href="https://xn--izc.com/posts/notes-on-fact-checking/" />
      <updated>2020-07-04T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/notes-on-fact-checking/</id>
      <content xml:lang="en" type="html">
        &lt;h1 id=&quot;fact-checking&quot;&gt;Fact Checking&lt;/h1&gt;
&lt;p&gt;Notes from &lt;a href=&quot;https://www.youtube.com/channel/UCX6b17PVsYBQ0ip5gyeme-Q&quot;&gt;Crash
Course&lt;/a&gt;’s excellent series about fact checking information you see on
the internet. The series starts &lt;a href=&quot;https://www.youtube.com/watch?v=pLlv2o6UfTU&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;three-questions&quot;&gt;Three Questions&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;How is behind this information?&lt;/li&gt;
&lt;li&gt;What is the evidence for their claims?&lt;/li&gt;
&lt;li&gt;What do other sources say about the organization and its
claims?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;“A question wrongly put.”&lt;/p&gt;
&lt;h2 id=&quot;lateral-reading&quot;&gt;Lateral Reading&lt;/h2&gt;
&lt;p&gt;All information is produced by someone, and is produced for a
purpose. The lines between motives are unclear. There are always
multiple motives, and they don’t always conflict.&lt;/p&gt;
&lt;p&gt;“Who made this and why?”&lt;/p&gt;
&lt;p&gt;We read websites like we read books. We read vertically. You are only
seeing what the creator wanted you to see. It is often impossible to
tell reliable information from unreliable information.&lt;/p&gt;
&lt;p&gt;A better alternative is to leave the site and search for
corroborating information. Look for conflicts of interest that are left
undisclosed which is a red flag.&lt;/p&gt;
&lt;p&gt;Newspapers can be a good start. These are now digital media
companies. Sometimes they have their own point-of-view. Sometimes these
are stated explicitly and/or are obvious. But that’s not necessarily
always the case.&lt;/p&gt;
&lt;p&gt;There is no magic arbiter of truth. All of these is created by humans
and humans make mistakes.&lt;/p&gt;
&lt;p&gt;“The media” doesn’t exist. It is a large and diverse industry. It is,
however, possible to take these diverse points of view into account.&lt;/p&gt;
&lt;p&gt;You should use Wikipedia. Not every article is perfect, but you
should see verifiable citations.&lt;/p&gt;
&lt;p&gt;Because no source is perfectly objective, one might conclude that no
source is trustworthy. This is not true.&lt;/p&gt;
&lt;h2 id=&quot;deciding-whom-to-trust&quot;&gt;Deciding Whom To Trust&lt;/h2&gt;
&lt;p&gt;It is easy to be mislead. None of us have the time to be an expert in
everything.&lt;/p&gt;
&lt;p&gt;We have to trust information from outside of ourselves we have to
find a way to accredit and trust experts, even though they will be wrong
some of the time.&lt;/p&gt;
&lt;p&gt;“Listen to me”bloviate””&lt;/p&gt;
&lt;p&gt;Before we place trust in a source, we should verify the authority,
and the validity of their evidence.&lt;/p&gt;
&lt;h3 id=&quot;investigating-a-sources-authority&quot;&gt;Investigating A Source’s
Authority&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The author or authors’ professional background.&lt;/li&gt;
&lt;li&gt;The process they used to produce that information.&lt;/li&gt;
&lt;li&gt;The systems that are in place to catch mistakes and correct
them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everyone has a perspective influenced by their lived experience. This
doesn’t necessarily mean that they are unfairly biased. We should take
their perspective into consideration when examining their arguments.
They may be presenting their information in a way that’s persuasive.&lt;/p&gt;
&lt;p&gt;“Opinion”, “Analysis” etc. mean that the work intends to be
persuasive rather than informative.&lt;/p&gt;
&lt;p&gt;STOP, THINK, and LOOK AROUND.&lt;/p&gt;
&lt;p&gt;Each bit of information we have about a source gives us a lens to
filter out their perspective.&lt;/p&gt;
&lt;h2 id=&quot;using-wikipedia&quot;&gt;Using Wikipedia&lt;/h2&gt;
&lt;p&gt;When used correctly Wikipedia can be a great place to start when
verifying the legitimacy of a source. It’s breadth can exceed any
newspaper. It gives you the general lay of the land when exploring or
researching a topic.&lt;/p&gt;
&lt;p&gt;Wikipedia has become the internet’s largest general reference
work.&lt;/p&gt;
&lt;p&gt;Their content policies:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;A neutral point of view.&lt;/li&gt;
&lt;li&gt;No original research.&lt;/li&gt;
&lt;li&gt;Verifiable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Modern Wikipedia has rigorous and robust mechanisms to keep things in
check.&lt;/p&gt;
&lt;p&gt;Wikipedia is not a one-stop shop for in-depth research. Don’t cite
Wikipedia. That’s not a good look. And encyclopedia is not a source.&lt;/p&gt;
&lt;p&gt;Citations help bring up more information from reputable sources.&lt;/p&gt;
&lt;p&gt;Treat Wikipedia as a launch pad.&lt;/p&gt;
&lt;p&gt;Wikipedia is another tool in your information evaluation tool
kit.&lt;/p&gt;
&lt;p&gt;You go there for general overview a topic or a stepping stone to more
references, or to use as one lateral reading source among several.&lt;/p&gt;
&lt;p&gt;And as long as your know how and when to use it appropriately,
Wikipedia can be a great friend.&lt;/p&gt;
&lt;h2 id=&quot;evaluating-evidence&quot;&gt;Evaluating Evidence&lt;/h2&gt;
&lt;p&gt;As you get older “because I said so” doesn’t cut it anymore. You need
to provide evidence and that evidence should be convincing.&lt;/p&gt;
&lt;p&gt;“What is the evidence?”&lt;/p&gt;
&lt;p&gt;Often when the evidence does not support the claim, it is misleading
or disinformation. Lack of evidence should be suspicious
immediately.&lt;/p&gt;
&lt;p&gt;The mere existence of evidence doesn’t support the claim either.&lt;/p&gt;
&lt;p&gt;Not all evidence is cerated equal.&lt;/p&gt;
&lt;p&gt;The evidence a source provides should come from another reputable
source.&lt;/p&gt;
&lt;p&gt;“Thousands of people never conspire to do anything secretly.”&lt;/p&gt;
&lt;p&gt;Spurious correlation: The implied causal relationship between events
that are coincidentally linked.&lt;/p&gt;
&lt;p&gt;The quality of our evidence like the quality of our information,
affects the quality of our decisions.&lt;/p&gt;
&lt;h2 id=&quot;evaluating-photos-videos&quot;&gt;Evaluating Photos &amp;amp; Videos&lt;/h2&gt;
&lt;p&gt;Photographs feel real and authentic. Even when images aren’t altered,
they are selectively framed, or have their context falsified (e.g. with
a false explanation, or date).&lt;/p&gt;
&lt;p&gt;We are used to thinking that “seeing is believing”.&lt;/p&gt;
&lt;p&gt;Thanks to their power, images are a very common form of online
evidence. But just like data or text image-based evidence can be
&lt;strong&gt;relevant&lt;/strong&gt; and &lt;strong&gt;reliable&lt;/strong&gt;, or
&lt;strong&gt;irrelevant&lt;/strong&gt; and &lt;strong&gt;unreliable&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When you encounter a suspicious image online it is crucial to
investigate who is behind it and whiter they are a reliable source. We
also must verify the surrounding context and whether it supports any
claims being made.&lt;/p&gt;
&lt;p&gt;Use reverse image search on Google to track down sources. Turn to
fact checking sites like Snopes and Politifact.&lt;/p&gt;
&lt;p&gt;Videos can also be dramatically altered. It is important to know
where a video came from, who created it, and whether it’s been altered
before you believe what you see.&lt;/p&gt;
&lt;h2 id=&quot;data-and-infographics&quot;&gt;Data and infographics&lt;/h2&gt;

      </content>
    </entry>
    <entry>
      <title>Easier CLI for ad-hoc Ansible tasks and playbooks</title>
      <link href="https://xn--izc.com/posts/ansible-cli-sugar/" />
      <updated>2020-06-01T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/ansible-cli-sugar/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;This article is about using &lt;a href=&quot;https://ansible.com/&quot;&gt;Ansible&lt;/a&gt;
on the command-line.&lt;/p&gt;
&lt;h2 id=&quot;problem&quot;&gt;Problem:&lt;/h2&gt;
&lt;p&gt;You …&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;… want a convenient way to do ad-hoc tasks on a bunch of
machines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… already have a few playbooks and machine groups defined in your
inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… don’t want to invest too much into Ansible because you have
other things to do and Ansible is just a tool to deal with one aspect of
what you want to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… live on the command-line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… think &lt;code&gt;ansible-playbook&lt;/code&gt; and &lt;code&gt;ansible&lt;/code&gt;
commands have too many knobs and too few knobs at the same
time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;a-possible-solution&quot;&gt;A Possible Solution&lt;/h2&gt;
&lt;p&gt;Taking a page from old school Posix tools, let’s make a script that
encodes Ansible group names into the filename.&lt;/p&gt;
&lt;p&gt;Then you can go from this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ansible atlanta &lt;span class=&quot;at&quot;&gt;-m&lt;/span&gt; copy &lt;span class=&quot;at&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;src=/etc/hosts dest=/tmp/hosts&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ansible webservers &lt;span class=&quot;at&quot;&gt;-m&lt;/span&gt; service &lt;span class=&quot;at&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;name=httpd state=started&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; atlanta copy &lt;span class=&quot;st&quot;&gt;&amp;quot;src=/etc/hosts dest=/tmp/hosts&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; webservers service &lt;span class=&quot;st&quot;&gt;&amp;quot;name=https state=started&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or from this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ansible-playbook &lt;span class=&quot;at&quot;&gt;-l&lt;/span&gt; atlanta go-to-the-moon&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ansible-playbook &lt;span class=&quot;at&quot;&gt;-l&lt;/span&gt; webservers do-the-other-things&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; atlanta go-to-the-moon&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; webservers do-the-other-things&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;setting-up&quot;&gt;Setting Up&lt;/h2&gt;
&lt;p&gt;These are just examples. Please don’t spend time bikeshedding names
because you can use whichever names you like.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Download the contents of &lt;code&gt;ansible-by-proxy&lt;/code&gt; from &lt;a href=&quot;https://github.com/asankah/ansible-cli-sugar/blob/master/ansible-by-proxy&quot;&gt;here&lt;/a&gt;.
It’s a starter script that includes a bunch of sensible settings
expressed via environment variables. Remove or change these to match
your needs.&lt;/p&gt;
&lt;p&gt;Note that the script expects to find a sub-directory called
&lt;code&gt;ansible&lt;/code&gt; in the same directory as the script which contains
the playbooks and the inventory file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store this file somewhere on the system &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Don’t forget to mark the file as executable if it isn’t already.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; chmod +x ansible-by-proxy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create symlinks to the file that have the same name as hostnames
or groups as described in the includes:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ln &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt; ansible-by-proxy atlanta&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;https://xn--izc.com/posts/ansible-cli-sugar/#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ln &lt;span class=&quot;at&quot;&gt;-s&lt;/span&gt; ansible-by-proxy webservers&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and so on.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. Now you can invoke playbooks and tasks just by using the
name of host or group.&lt;/p&gt;

      </content>
    </entry>
    <entry>
      <title>Identity Domains</title>
      <link href="https://xn--izc.com/posts/identity-domains/" />
      <updated>2020-05-01T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/identity-domains/</id>
      <content xml:lang="en" type="html">
        &lt;blockquote&gt;
&lt;p&gt;An &lt;strong&gt;Identity domain&lt;/strong&gt; is a scope within which we
consider it a given that the user has a shared or trivially joinable
identity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a privacy boundary, not a security boundary. Hence it assumes
that where possible all sites share information.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/identity-domains/identity-domains.png&quot; class=&quot;noinvert&quot; alt=&quot;Diagram of example identity domains described below&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Diagram of example identity domains
described below&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Above is a diagram showing relationships between clusters of
documents and identity domains.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;foo.example&lt;/code&gt; and &lt;code&gt;baz.example&lt;/code&gt; belong to the
same first party set.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a.example&lt;/code&gt; has no first-party relationship with any
other domain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;em&gt;Identity domain&lt;/em&gt; has the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#active-document&quot;&gt;active
documents&lt;/a&gt; in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#list-of-the-descendant-browsing-contexts&quot;&gt;descendent
browsing contexts&lt;/a&gt; belong to the same &lt;strong&gt;identity
domain&lt;/strong&gt; as the active document in the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#top-level-browsing-context&quot;&gt;top-level
browsing context&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See each cluster of browsing contexts in the diagram above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All active documents in top-level browsing contexts that share
the same &lt;a href=&quot;https://html.spec.whatwg.org/multipage/webappapis.html#site&quot;&gt;site&lt;/a&gt;
also share the same &lt;strong&gt;identity domain&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the diagram above, &lt;code&gt;foo.example&lt;/code&gt; in cluster 1 and
&lt;code&gt;baz.example&lt;/code&gt; in cluster 2 belong to the same first-party
set, hence they are considered to belong to the same identity domain.
However &lt;code&gt;a.example&lt;/code&gt; in cluster 3 does not belong to the same
identity domain because there’s no first party relation between
&lt;code&gt;a.example&lt;/code&gt; and any other top level domain in the
diagram.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All &lt;strong&gt;private client state&lt;/strong&gt; including but not
limited to open sockets, socket pools, cookies, storage, permissions /
content settings, transient caches of credentials, cached resources,
service workers, and shared workers accessible to any document in an
identity domain also belong to the &lt;strong&gt;&lt;em&gt;identity
domain&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identity domains&lt;/strong&gt; don’t span browser
profiles.&lt;/p&gt;
&lt;p&gt;See clusters 1 and 4 in the diagram above. Both share top-level
origins, but don’t share identity domains because they are in two
different browser profiles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identity domains&lt;/strong&gt; don’t span browsers.&lt;/p&gt;
&lt;p&gt;Derived from above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identity domains&lt;/strong&gt; don’t survive browsing data
erasures.&lt;/p&gt;
&lt;p&gt;Erasing an identity domain – and thus an identity – requires
destroying all private client state mentioned previously. Hence erasing
an identity domain involves discarding all &lt;code&gt;Document&lt;/code&gt; objects
and workers in that identity domain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that in the existing web privacy model third-parties can
trivially associate identities across top-level contexts. Thus the
entire internet essentially amalgamates into a single identity
domain.&lt;/p&gt;
&lt;p&gt;The boundaries discussed herein require moving to a different model
of identity on the web. The privacy threat model guiding this model is
discussed in PING’s &lt;a href=&quot;https://w3cping.github.io/privacy-threat-model/&quot;&gt;Target Privacy
Threat Model&lt;/a&gt; document which is a work in progress as of this
writing.&lt;/p&gt;
&lt;h2 id=&quot;additional-notes-and-observations&quot;&gt;Additional Notes and
Observations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The identity domain is a privacy boundary. The boundary is
something that’s asserted by the user-agent and doesn’t depend on the
cooperation of sites. I.e. assumes that sites involved are worst case
actors.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not to be confused with security boundaries like those imposed via
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;Content
Security Policy&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The definition assumes that sites can share information
out-of-band. The identity domain boundary does not require sites to
cooperate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The same site can appear in multiple identity domains. For
example, re-identification is equivalent to a single site joining an
identity across disjoint domains.&lt;/p&gt;
&lt;p&gt;One can also imagine a user-agent that maintains multiple identity
boundaries for the same top-level site for the purpose of allowing
multiple sets of cookies to be used from the same device.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two identity domains can be joined by sharing a unique identifier
between the two domains.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;WRT federated identity (as detailed in &lt;a href=&quot;https://github.com/samuelgoto/WebID&quot;&gt;WebID&lt;/a&gt;) multiple relying
parties join identity domains by virtue of shared unique identifiers
like email address. Similarly identity providers can also generate and
use unique identifiers linking domains.&lt;/p&gt;
&lt;p&gt;We likely need another term for describing externally joined identity
domains. In such cases the UA doesn’t necessarily know or can prevent
joining of identity domains.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concepts like “logging out” can be defined in terms of destroying
an identity domain on the User Agent.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
    <entry>
      <title>Ephemeral Fingerprinting On The Web</title>
      <link href="https://xn--izc.com/posts/ephemeral-fingerprinting/" />
      <updated>2020-04-01T00:00:00Z</updated>
      <id>https://xn--izc.com/posts/ephemeral-fingerprinting/</id>
      <content xml:lang="en" type="html">
        &lt;p&gt;TL;DR:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Any web observable property whose changes are concurrently
observable by multiple top-level sites can lead to cross site identity
joining.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This method of identity joining does not require additional
coordination between multiple first parties. A single third party
embedded within multiple first parties can also use this
method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/isolation-boundaries.png&quot; alt=&quot;diagram of site isolation boundaries with overlap&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;diagram of site isolation boundaries with
overlap&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Figure 1&lt;/strong&gt;: Two sites observe a sequence of device
orientation changes at times 𝒕₀, 𝒕₁,𝒕₂ .&lt;/p&gt;
&lt;p&gt;All sites on the same UA instance share a clock and therefore can
agree on the timestamps with a small margin of error. The triplet 𝒕₀,
𝒕₁,𝒕₂ has a high probability of uniquely identifying the user. The two
sites can thus use these observations to conclude that the observations
originate from the same user.&lt;/p&gt;
&lt;p&gt;As illustrated above, one or more low entropy signals observed
concurrently can be used to identify a user with a high degree of
confidence. Let’s call these &lt;strong&gt;ephemeral fingerprints&lt;/strong&gt;.
This document discusses two types:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The sequence of timestamps corresponding to observed changes
of a volatile surface can be used for identification&lt;/em&gt;. Let’s call
these &lt;strong&gt;correlated events&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;A stream of observations of a volatile surface can be
identifying&lt;/em&gt;. Let’s call these &lt;strong&gt;unique event
streams&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Signals considered for ephemeral fingerprinting don’t need to be
highly identifying by themselves. The &lt;a href=&quot;https://github.com/bslassey/privacy-budget&quot;&gt;privacy budget
proposal&lt;/a&gt; does not adequately account for fingerprinting based on
concurrent observations of low entropy signals.&lt;/p&gt;
&lt;p&gt;Device orientation, from our earlier example, can take one of two
values (portrait or landscape) and is unstable. Thus a single sample of
device orientation carries almost no information. I.e. A recorded
observation of device orientation doesn’t help at all with identifying
the user at a later time. However the timestamps corresponding to
orientation changes could have identifying levels of entropy.&lt;/p&gt;
&lt;p&gt;These are not new. For example, this is discussed by Van Goethem et.
al. &lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fn1&quot; class=&quot;footnote-ref&quot; id=&quot;fnref1&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;who calls these “Cross-Session Events” (§ 5 of linked paper).
Potential ephemeral fingerprinting surfaces also get flagged during
standardization discussions ( &lt;a href=&quot;https://github.com/w3c/mediacapture-main/issues/403&quot;&gt;Example:
Polling enumerateDevices&lt;/a&gt;, &lt;a href=&quot;https://lists.w3.org/Archives/Public/public-privacy/2013JanMar/0007.html&quot;&gt;Example:
Ambient light events&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;modelling-correlated-events&quot;&gt;Modelling Correlated Events&lt;/h3&gt;
&lt;p&gt;A correlatable event can be thought of as the tuple
&lt;code&gt;&amp;lt;surface-sample, timestamp&amp;gt;&lt;/code&gt;. The addition of the
timestamp strictly increases the amount of information carried by the
surface sample.&lt;/p&gt;
&lt;h3 id=&quot;modelling-event-streams&quot;&gt;Modelling Event Streams&lt;/h3&gt;
&lt;p&gt;An event stream is simply a list of observed samples
&lt;code&gt;sample₀, sample₁, ...&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each additional observation strictly increases the amount of
information.&lt;/p&gt;
&lt;h3 id=&quot;other-examples&quot;&gt;Other Examples:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Accelerometer&lt;/code&gt; properties.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sensor&lt;/code&gt;, &lt;code&gt;onreading&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BatteryManager.onlevelchange&lt;/code&gt; : Deprecated but still
shipping.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bluetooth.onadvertisementreceived&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BroadcastChannel&lt;/code&gt;, all events.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MediaDevices.devicechange&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GlobalEventHandlers.onfocus&lt;/code&gt; and &lt;code&gt;onblur&lt;/code&gt;
events can fire simultaneously when switching between two browser
windows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;mitigation&quot;&gt;Mitigation&lt;/h2&gt;
&lt;h3 id=&quot;permissions&quot;&gt;Permissions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Require informed consent from users.&lt;/p&gt;
&lt;p&gt;There’s precedent for considering permissions &lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fn2&quot; class=&quot;footnote-ref&quot; id=&quot;fnref2&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; to
be sufficient mitigation for similar issues. For example, the Media
Capture API specification includes the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For origins to which permission has been granted, the devicechange
event will be emitted across browsing contexts and origins each time a
new media device is added or removed; user agents can mitigate the risk
of correlation of browsing activity across origins by fuzzing the timing
of these events.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: right&quot;&gt;
From §15 of &lt;a href=&quot;https://w3c.github.io/mediacapture-main/#privacy-and-security-considerations&quot;&gt;Media
Capture and Streams API&lt;/a&gt; specification.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prevents drive-by fingerprinting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;UI for permissions don’t disclose the fact that all sites that
have been granted access to the same resource can synchronize
identifiers as a side-effect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Doesn’t prevent identity joining once permission is
granted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;fuzzing-timing-of-events&quot;&gt;Fuzzing Timing of Events&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Deter correlation of events by injecting
timing skew.&lt;/p&gt;
&lt;p&gt;Mentioned in the snippet above from the Media Capture and Streams API
and called out by Jeffrey Yasskin as a potential general mitigation in
“desynchronize whole-browser events” in &lt;a href=&quot;https://github.com/whatwg/html/issues/5215&quot;&gt;this issue&lt;/a&gt; filed
against the WHATWG HTML specification.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lowers confidence of identity equivalence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Precise timing may not be required. I.e. the lowered level of
confidence could still be sufficient for most uses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Doesn’t address unique event streams.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;first-party-restriction-for-apis&quot;&gt;First-Party Restriction for
APIs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Deter identity correlation by third-party
sites.&lt;/p&gt;
&lt;p&gt;Restrict APIs to the origin of the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#top-level-browsing-context&quot;&gt;top-level
browsing context&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The latter may choose to explicitly delegate access to the APIs via
&lt;a href=&quot;https://w3c.github.io/webappsec-feature-policy/&quot;&gt;feature
policies&lt;/a&gt;. But third-party contexts can’t “reach across” browsing
contexts via correlation of cross context events or attributes that may
be made available by the API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Makes it a requirement that first-parties actively cooperate with
other first-parties or third-parties. I.e. Good first-party + bad
third-party = safe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Difficult to retrofit into existing APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Browser-wide events and attributes are still visible to distinct
top-level browsing contexts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In practice top-level browsing contexts contain a fair amount of
third party scripts which may access the same APIs. Furthermore there
are financial incentives for first-parties to delegate API access to
third-parties.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limit-api-access-to-visible-browsing-contexts&quot;&gt;Limit API Access
To Visible Browsing Contexts&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Prevent background browsing contexts from
skimming identifiable events.&lt;/p&gt;
&lt;p&gt;The Page Visibility API defines the &lt;a href=&quot;https://w3c.github.io/page-visibility/#visibility-states&quot;&gt;visibility
state of a document&lt;/a&gt; as &lt;code&gt;visible&lt;/code&gt; if the document is
&lt;em&gt;“at least partially visible on at least one screen”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Restrict APIs to — possibly top-level — browsing context’s active
document.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is a convincing mitigation on mobile devices where only one
top-level document can be visible at the same time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There could be multiple visible browsing contexts which still
leaves the door open for identity correlation across site
boundaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The fact that having more than one browsing context open at the
same time is a privacy risk is quite surprising for users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limit-events-to-focused-top-level-browsing-context&quot;&gt;Limit Events
To Focused Top-Level Browsing Context&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Limit firing correlatable events to a single
&lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#top-level-browsing-context&quot;&gt;top-level
browsing context&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The HTML spec defines a concept of a &lt;em&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/interaction.html#currently-focused-area-of-a-top-level-browsing-context&quot;&gt;currently
focused area of a top-level browsing context&lt;/a&gt;&lt;/em&gt;. As defined, every
top level &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#browsing-context&quot;&gt;browsing
context&lt;/a&gt; has one regardless of visibility. A similar narrow concept
could be introduced that recognizes the top level browsing context that
has system input focus. There should be only one of these on a single
device.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Let’s call the top-level browsing context that has system input
focus as the&lt;/em&gt; &lt;strong&gt;focused top-level browsing
context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;New specifications could restrict browser-wide events to the focused
top-level browsing context.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Likely fits in well with the intended usage model for most
APIs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Does not address event stream fingerprinting via polling.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;limit-api-access-to-focused-top-level-browsing-context&quot;&gt;Limit
API Access To Focused Top-Level Browsing Context&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Limit access to sensitive APIs to a single &lt;a href=&quot;https://html.spec.whatwg.org/multipage/browsers.html#top-level-browsing-context&quot;&gt;top-level
browsing context&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Similar to the above, but addresses issues around polling by
disallowing access to the entire API or sensitive attributes by
restricting the entire API instead of just events.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Resilient to event stream fingerprinting via polling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can’t be easily retrofitted to existing APIs since it requires
defining behavior for “disabled” APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;May break critical use cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;secure-context-restriction-and-control-via-feature-policy&quot;&gt;Secure-Context
Restriction and Control via Feature-Policy&lt;/h3&gt;
&lt;p&gt;These should be pretty standard at this point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Just makes sense.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not sufficient by itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;spotting-ephemeral-fingerprinting-surfaces-in-web-specs&quot;&gt;Spotting
Ephemeral Fingerprinting Surfaces In Web Specs&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ephemeral fingerprints:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Require that multiple browsing contexts observe the same events
or access the same volatile attribute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;These browsing contexts could involve a single third party in
multiple first party contexts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does not require precise clocks nor agreement on the exact
timestamps of the observed events. Depending on the fingerprintable
surfaces involved the sequence of events could be identifiable by
itself. Servers can roughly bucket observations by time periods,
eliminating the need for client-side clocks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does not require an API to fire an event. A property with a
volatile value that can be polled periodically is sufficient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-to-look-for&quot;&gt;What to look for:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Events with external triggers. E.g. hardware based
events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple distinct events that are fired in tandem to distinct
browsing contexts. E.g. any processing model where multiple events are
fired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Volatile attributes that are visible across browsing
contexts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Volatile attributes that don’t share values across browsing
contexts, but change simultaneously. E.g. Salting a volatile attribute
is insufficient if its mutations can be correlated.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Consider &lt;code&gt;onfocus&lt;/code&gt; and &lt;code&gt;onblur&lt;/code&gt; events.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://html.spec.whatwg.org/multipage/interaction.html#focus-update-steps&quot;&gt;focus
update steps&lt;/a&gt; involve firing up to three distinct events:
&lt;code&gt;change&lt;/code&gt; if the node losing focus is an &lt;code&gt;input&lt;/code&gt;
element, &lt;code&gt;focus&lt;/code&gt;, and &lt;code&gt;blur&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When focus traverses a browsing context boundary, these events may be
fired simultaneously to two different browsing contexts. Browsers
mitigate this by not firing &lt;code&gt;blur&lt;/code&gt; for cross site tab
switches, but they still fire &lt;code&gt;blur&lt;/code&gt; when the browser itself
goes out of focus. Thus identity can be correlated when switching
browser windows.&lt;/p&gt;
&lt;h4 id=&quot;possible-mitigation&quot;&gt;Possible Mitigation&lt;/h4&gt;
&lt;p&gt;When the &lt;em&gt;new chain&lt;/em&gt; and the &lt;em&gt;old chain&lt;/em&gt; &lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fn3&quot; class=&quot;footnote-ref&quot; id=&quot;fnref3&quot; role=&quot;doc-noteref&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; are
in different top-level browsing contexts whose active documents are not
same-origin, queue but don’t fire &lt;code&gt;change&lt;/code&gt; and
&lt;code&gt;blur&lt;/code&gt; events until focus returns to the old top-level
browsing context.&lt;/p&gt;
&lt;h3 id=&quot;notes&quot;&gt;Notes&lt;/h3&gt;
&lt;section id=&quot;footnotes&quot; class=&quot;footnotes footnotes-end-of-document&quot; role=&quot;doc-endnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Van Goethem, T. and Joosen, W., 2017. One side-channel
to bring them all and in the darkness bind them: Associating isolated
browsing sessions. In &lt;em&gt;11th {USENIX} Workshop on Offensive
Technologies ({WOOT} 17)&lt;/em&gt;. (&lt;a href=&quot;https://pdfs.semanticscholar.org/5814/9610a57cb4626918bf003b8bad25e740b1f4.pdf&quot;&gt;PDF&lt;/a&gt;)&lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fnref1&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;Either via a legacy permissions prompt or explicitly
requiring the use of the &lt;a href=&quot;https://w3c.github.io/permissions/&quot;&gt;Permissions API&lt;/a&gt; in the
spec for sensitive APIs.&lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fnref2&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;&lt;em&gt;New chain&lt;/em&gt; and &lt;em&gt;old chain&lt;/em&gt; are defined in
&lt;a href=&quot;https://html.spec.whatwg.org/multipage/interaction.html#focus-update-steps&quot;&gt;focus
update steps&lt;/a&gt;.&lt;a href=&quot;https://xn--izc.com/posts/ephemeral-fingerprinting/#fnref3&quot; class=&quot;footnote-back&quot; role=&quot;doc-backlink&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

      </content>
    </entry>
</feed>
