chore: Rename to Lain

This commit is contained in:
Robert Prehn 2025-01-10 16:30:05 -06:00
parent 78f677b98b
commit 78b00b30a5
No known key found for this signature in database
74 changed files with 74 additions and 1781 deletions

2
.gitignore vendored
View file

@ -20,7 +20,7 @@ erl_crash.dump
*.ez
# Ignore package tarball (built via "mix hex.build").
pre_dot_hn-*.tar
lain-*.tar
# Temporary files, for example, from tests.
/tmp/

View file

@ -10,7 +10,7 @@ pages:
- mix tree_sitter.install --if-missing
- (cd tree-sitter/_parsers/;git clone https://github.com/elixir-lang/tree-sitter-elixir; git clone https://github.com/camdencheek/tree-sitter-dockerfile)
- mix assets.build
- mix pre_dot_hn.build
- mix lain.build
- cp -r priv/static/ public
artifacts:
paths:
@ -31,4 +31,4 @@ ping:
- mix local.rebar --force
- mix deps.get
- mix compile
- mix pre_dot_hn.ping
- mix lain.ping

View file

@ -1,21 +1,21 @@
# PreDotHn
# Lain
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `pre_dot_hn` to your list of dependencies in `mix.exs`:
by adding `lain` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:pre_dot_hn, "~> 0.1.0"}
{:lain, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/pre_dot_hn>.
be found at <https://hexdocs.pm/lain>.

View file

@ -27,4 +27,4 @@ config :esbuild,
config :tree_sitter, version: "0.20.8", config_directory: "tree-sitter"
config :pre_dot_hn, host: "pre.hn", base: "https://pre.hn/"
config :lain, host: "pre.hn", base: "https://pre.hn/"

View file

@ -1,6 +1,6 @@
defmodule PreDotHn do
defmodule Lain do
@moduledoc """
Documentation for `PreDotHn`.
Documentation for `Lain`.
"""
use Phoenix.Component
@ -9,8 +9,8 @@ defmodule PreDotHn do
import Phoenix.LiveViewTest, only: [rendered_to_string: 1]
alias PreDotHn.Frontmatter
alias PreDotHn.Markdown
alias Lain.Frontmatter
alias Lain.Markdown
def read(path) do
path
@ -36,8 +36,9 @@ defmodule PreDotHn do
def validate(other), do: {:ok, other}
def clean() do
"priv/static/**"
def clean(base_path) do
base_path
|> Path.join("**")
|> Path.wildcard()
|> Enum.each(fn path ->
if File.dir?(path) do
@ -50,9 +51,10 @@ defmodule PreDotHn do
end)
end
def run() do
def run(path) do
posts =
"site/**/*.md"
path
|> Path.join("**/*.md")
|> Path.wildcard()
|> Enum.map(&read/1)
|> Enum.map(&validate/1)
@ -73,8 +75,8 @@ defmodule PreDotHn do
make_sitemap(posts)
index = make_index(posts)
PreDotHn.LinkLog.run()
PreDotHn.Static.run()
Lain.LinkLog.run(path)
Lain.Static.run(path)
Enum.map([index | posts], &write_page/1)
end
@ -109,7 +111,7 @@ defmodule PreDotHn do
def make_feed(posts) do
posts = posts |> Enum.reject(& &1.hidden) |> Enum.take(10)
base = Application.get_env(:pre_dot_hn, :base, "/")
base = Application.get_env(:lain, :base, "/")
assigns = %{base: base, posts: posts}
@ -220,7 +222,7 @@ defmodule PreDotHn do
<meta property="og:title" content={@title} />
<meta property="og:type" content="article" />
<meta property="og:url" content={"https://pre.hn/#{@slug}/"} />
<meta property="og:image" content="https://pre.hn/images/pre_dot_hn.png"} />
<meta property="og:image" content="https://pre.hn/images/lain.png"} />
<link rel="stylesheet" href="/assets/app.css">

View file

@ -1,4 +1,4 @@
defmodule PreDotHn.Application do
defmodule Lain.Application do
use Application
def start(_type, _args) do
@ -6,7 +6,7 @@ defmodule PreDotHn.Application do
{Bandit, plug: PreDotDn.DevServer}
]
opts = [strategy: :one_for_one, name: PreDotHn.Supervisor]
opts = [strategy: :one_for_one, name: Lain.Supervisor]
Supervisor.start_link(children, opts)
end
end

View file

@ -1,4 +1,4 @@
defmodule PreDotHn.Frontmatter do
defmodule Lain.Frontmatter do
@frontmatter_pattern ~r/---\r?\n/
def make_frontmatter(path, frontmatter_text) do

View file

@ -1,20 +1,20 @@
defmodule PreDotHn.LinkLog do
alias PreDotHn.Markdown
defmodule Lain.LinkLog do
alias Lain.Markdown
use Phoenix.Component
import Phoenix.LiveViewTest, only: [rendered_to_string: 1]
def run do
links = links()
def run(path) do
links = links(path)
make_feed(links)
links
|> make_index()
|> PreDotHn.write_page()
|> Lain.write_page()
end
def links do
link_path = Path.join(["site", "link-log.yaml"])
def links(path) do
link_path = Path.join(path, "link-log.yaml")
YamlElixir.read_from_file!(link_path)
end
@ -39,7 +39,7 @@ defmodule PreDotHn.LinkLog do
<title><%= Map.get(link, "emoji", "🔗") %> <%= HtmlSanitizeEx.strip_tags(link["name"]) %></title>
<content type="xhtml" xml:lang="en"
xml:base="https://pre.hn/"><![CDATA[<html><body>
<%= PreDotHn.Markdown.render(link["summary"]) %>
<%= Lain.Markdown.render(link["summary"]) %>
</body></html>]]>
</content>
<id>tag:pre.hn,<%= link["url"] %></id>

View file

@ -1,4 +1,4 @@
defmodule PreDotHn.Markdown do
defmodule Lain.Markdown do
@default_opts [pure_links: true, wikilinks: true, inner_html: false]
def render(source, opts \\ []) do
@ -81,5 +81,5 @@ defmodule PreDotHn.Markdown do
defp add_trailing_newline(string) when is_binary(string), do: "#{string}\n"
defp add_trailing_newline(other), do: other
defp host(), do: Application.get_env(:pre_dot_hn, :host)
defp host(), do: Application.get_env(:lain, :host)
end

View file

@ -1,6 +1,7 @@
defmodule PreDotHn.Static do
def run() do
"site/static/**/*"
defmodule Lain.Static do
def run(path) do
path
|> Path.join("static/**/*")
|> Path.wildcard()
|> Enum.each(fn path ->
build_path = String.replace(path, "site", "priv")

View file

@ -0,0 +1,7 @@
defmodule Mix.Tasks.Lain.Build do
use Mix.Task
def run([path]) do
Lain.run(path)
end
end

View file

@ -0,0 +1,7 @@
defmodule Mix.Tasks.Lain.Clean do
use Mix.Task
def run([path]) do
Lain.clean(path)
end
end

View file

@ -0,0 +1,8 @@
defmodule Mix.Tasks.Lain.DevServer do
use Mix.Task
def run(_args) do
Application.put_env(:lain, :serve_endpoints, true, persistent: true)
Mix.Tasks.Run.run(["--no-halt"])
end
end

View file

@ -1,4 +1,4 @@
defmodule Mix.Tasks.PreDotHn.Ping do
defmodule Mix.Tasks.Lain.Ping do
use Mix.Task
@urls [

View file

@ -1,7 +0,0 @@
defmodule Mix.Tasks.PreDotHn.Build do
use Mix.Task
def run(_args) do
PreDotHn.run()
end
end

View file

@ -1,7 +0,0 @@
defmodule Mix.Tasks.PreDotHn.Clean do
use Mix.Task
def run(_args) do
PreDotHn.clean()
end
end

View file

@ -1,8 +0,0 @@
defmodule Mix.Tasks.PreDotHn.DevServer do
use Mix.Task
def run(_args) do
Application.put_env(:pre_dot_hn, :serve_endpoints, true, persistent: true)
Mix.Tasks.Run.run(["--no-halt"])
end
end

View file

@ -1,9 +1,9 @@
defmodule PreDotHn.MixProject do
defmodule Lain.MixProject do
use Mix.Project
def project do
[
app: :pre_dot_hn,
app: :lain,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
@ -15,7 +15,7 @@ defmodule PreDotHn.MixProject do
# Run "mix help compile.app" to learn about applications.
def application do
[
mod: {PreDotHn.Application, []},
mod: {Lain.Application, []},
extra_applications: [:logger]
]
end

View file

@ -3,6 +3,6 @@
set -e
set -x
mix pre_dot_hn.build
mix lain.build
s3cmd sync -MP priv/static/ s3://pre.hn --exclude "*.css"
s3cmd put -P -m "text/css" priv/static/assets/app.css s3://pre.hn/assets/app.css

View file

@ -1,328 +0,0 @@
- url: https://kottke.org/24/11/trumps-historically-small-victory
name: "Trump's Historically Small Victory"
summary: |
A good reminder. I've seen a lot of folks decrying how it is possible that "so many people"
voted for Trump. The truth is, as of election night, he had a tiny margin in the popular vote.
In his other two elections, he lost by a larger margin. This is, of course, after decades of
voter suppression by the GOP, so it's hard to say he's genuinely favored by the majority of
people in this country.
- url: https://nochlin.com/blog/introducing-tuki
name: "Introducing, Tuki!"
summary: |
Tuki is an open source utility for adding a little structure to running one-off commands
in production. It's an interesting approach to a problem that I've encountered at a lot of
clients. I'm actually working on a slightly different solution (and obviously I like my
version more or I wouldn't be building it!).
- url: https://summereternal.com/#manifesto
name: "Summer Eternal: Manifesto"
summary: |
Some of the people behind Disco Elysium have formed a new co-op to make new games and their
manifesto rules. You can tell this was written by BAFTA-winning writers.
- url: https://www.youtube.com/watch?v=uFyk5UOyNqI
name: "Joseph Cox: Def Con 32 - Inside the FBIs Secret Encrypted Phone Company Anom"
summary: |
Joseph gives a quick overview of Anom, the encrypted phone company beloved by high-end
criminals around the world. The wrinkle: Anom was secretly being run by the FBI.
I've added Dark Wire, Joseph's much more in-depth book on Anom to my pile for reading soon!
- url: https://bsky.app/profile/adamcsharp.bsky.social/post/3l5yyo2azng26
name: "A Bluesky Thread of Videos That Line Up Really Well with Songs"
summary: |
A variety of delightful videos that line up really well with songs.
- url: https://sketchplanations.com/how-to-speak-plainly-by-pooh-bear
name: "Sketchplanations: How to Speak Plainly According to Pooh Bear"
summary: |
I'm prone to "Owl-speak." As usual, it's a good idea to be more like Pooh Bear.
- url: https://ttl.blog/the-big-multitasking-lie/
name: "Paolo Belcastro: The Big Multitasking Lie"
summary: |
There is no such thing as multi-tasking. Even computers don't run more than
one task at a time (at least on a single CPU core / "brain"). What they do is
time-slice. But time slicing has a cost if you do it too often, especially
if you aren't a computer.
- url: https://www.destroyallsoftware.com/talks/wat
name: "Gary Bernhardt: Wat"
summary: |
A classic of programming lightning talks.
- url: https://www.brightball.com/articles/story-points-are-pointless-measure-queues
name: "Barry Jones: Story Points are Pointless, Measure Queues"
summary: |
Well worth the read if you make software on an "agile" team. First, Barry
explains why "story points" don't work. Then Barry outlines what to do
instead.
It's brilliant to apply queueing theory and Little's Law to estimate delivery
of software in a queue. As software engineers we know it works for job and
message queues. Why wouldn't it work for development queues?
- url: https://jordankaye.dev/posts/go-slow-move-fast/
name: "Jordan Kaye: Go Slow to Move Fast"
summary: |
A great take on the concept of "technical debt."
Two key takeaways:
1. "Slow is smooth, smooth is fast."
2. It's only technical debt if it's intentional. Otherwise, it's just bad code.
- url: https://heydingus.net/blog/2024/8/you-and-i-can-do-hard-things
name: "Jarrod Blundy: You (and I) Can Do Hard Things"
summary: |
It's good to be reminded sometimes.
- url: https://www.mitchellhanberg.com/the-comprehensive-guide-to-elixirs-for-comprehension/
name: "Mitchell Hanberg: The Comprehensive Guide to Elixirs for Comprehension"
summary: |
I saw this guide linked from the Elixir Slack and it is the best guide to comprehensions
and the `for` special form in Elixir that I've seen. I write Elixir code every day and I had
no idea about some of the options. See also: [the official documentation for comprehensions](https://hexdocs.pm/elixir/comprehensions.html).
- url: https://public.work/
name: "public.work"
summary: |
This is a great search engine for public domain images.
- url: https://gregmorris.co.uk/2024/07/22/why-the-rcs.html
name: "Greg Morris: Why The RCS Hate?"
summary: |
Apple's implementation of RCS is a perfunctory, letter-of-the-law effort. Their messaging
blames the EU instead of acknowledging their half-assed approach toward the technology. And
prominent Apple bloggers are providing cover for it, instead of using their influence to
hold the company to account.
- url: https://marco.org/2024/07/16/overcast-rewrite
name: "Marco Arment: Ten years of Overcast: A new foundation"
summary: |
This is an example of what a software update that actually serves users looks like--
something that is sadly a rarity these days.
- url: https://www.tbray.org/ongoing/When/202x/2024/07/12/2009-Ranger
name: "Tim Bray: 2009 Ranger"
summary: |
> Car companies: Dare to do less · I couldnt possibly walk away from our time in the Ranger
> without thinking about the absolutely insane amounts of money and resources and carbon
> loading we could save by building smaller, simpler, cheaper, dumber, automobiles.
Please, yes. In the last 15-20 years, auto makers, particularly US auto makers have completely
abandoned the basic sedan market and the _actual_ light truck market. Before that, base sedans
and trucks were intentionally sabotaged (e.g. base trim without aircon) so that dealerships
could upsell you expensive packages (e.g. aircon plus a bunch of shiny bits you don't care about
for $5,000).
I feel like there's an opportunity for someone to change the game with a car like this:
- ✅ A stero system that is basically a dash-mounted $20 bluetooth speaker and one USB port
- ✅ Aircon.
- ✅ An eye toward user-serviceable.
- ✅ Cheap, reliable, and durable.
- ❌ No other computer-y or electronic bits.
- url: https://maggieappleton.com/home-cooked-software
name: "Maggie Appleton: Home-Cooked Software and Barefoot Developers"
summary: |
I love so much about this presentation. I believe in the power of writing simple, rough software
for small communities, or even for communities of one (e.g. yourself). I've done a lot of that.
I also have been feeling the pull of local-first software with really simple tech stacks. That
might be my disillusionment with the complexity of modern DevOps.
That said, I don't buy that LLMs are going to suddenly allow a lot of people who have never coded
before to start coding. Every LLM-based coding tool I've tried has been basically IntelliSense, but
with more variance (plus and minus). To say that people without any other assistance can use
IntelliSense to develop whole applications would be nonsense, and so far, I think it's the same
for LLMs. Now, does richer developer tooling lower the barrier to entry? Certainly.
- url: https://jeffhuang.com/productivity_text_file/
name: "Jeff Huang: My productivity app is a never-ending .txt file"
summary: |
My system is pretty similar to this, though I'm still living the one-file-per-day life. I've tried
just about all the options out there, and for me, the one that has the lowest friction and highest
interoperability is text files.
It also reminds me of the adage I've heard repeated many times about David Allen's Getting Things Done system: "if you
can't do GTD with a pen and paper, you aren't really doing GTD."
- url: https://pcalv.es/mosh-pit-rules-applied-to-social-media/
name: "Mosh pit rules applied to social media"
summary: |
As an old punk, I love this.
Though, I'd much rather be in a terrible mosh pit than an average social media site.
- url: https://wireframer.design/
name: "Wireframer"
summary: |
Cool idea— a font to replace distracting lorem ipsum.
I feel like this solution isn't ideal. My preference is for writing-first design i.e. forcing the
client to write their message before you start creating high-fidelity design assets. And I think if
I were in a situation where placeholders were appropriate, I think I would prefer something that
still _felt_ like glyphs. I feel like the first question from a client would be "what's with all of
these blocks everywhere?"
- url: https://www.youtube.com/watch?v=DHHqQDKzjTg
name: "Struthless: The Answer Isn't Online Masculinity"
emoji: "📺"
summary: |
If you don't know Struthless (Campbell Walker) yet, he's making some of the best video essays about creativity, life improvement, mindset, and internet culture on YouTube right now. Go check out his stuff.
In this one, he tackles the "radioactive" subject of masculinity. I know what you're thinking. Uh oh. Is he for or against masculinity? Which camp is he in? Watch the video.
- url: https://ludic.mataroa.blog/blog/i-will-fucking-piledrive-you-if-you-mention-ai-again/
name: " Nikhil Suresh: I Will Fucking Piledrive You If You Mention AI Again"
summary: |
Yeah, this pretty much sums it up.
- url: https://www.reddit.com/r/Fantasy/comments/vdt11/comment/c53o23x/
name: "Kids need to get answers from humans who love them."
summary: |
Neil Stephenson wrote _The Diamond Age: Or, A Young Lady's Illustrated Primer_, a
novel featuring an AI storybook which teaches the protagonist. A Redditor asked him
"My ultimate goal in life is to make the Primer real. Anything you want to make sure I get right?."
Neal simply replied "Kids need to get answers from humans who love them."
I wish the generative AI people would take that wisdom to heart.
- url: https://simonwillison.net/2024/May/8/slop/
name: "Slop is the new name for unwanted AI-generated content"
summary: |
> Watching in real time as “slop” becomes a term of art. the way that “spam” became the term for unwanted emails, “slop” is going in the dictionary as the term for unwanted AI generated content.
_Slop_. I love (/hate) it.
- url: https://brettharned.com/they-broke-the-cookie-cutter/
name: "Brett Harned: They broke the cookie cutter!"
summary: |
> Essentially, Scrum Masters are corporate dog trainers. Command, control, and structure strengthen the pack and the bottom line. Once they're trained, it's time to move on
I wish more people in the software business understood this. Having permanent, full-time Scrum Masters is an anti-pattern. Their prescence, at least in the long term, is a sign that you don't actually have an empowered agile product team.
- url: https://www.citationneeded.news/we-can-have-a-different-web/
name: "Molly White: We can have a different web"
summary: |
> The thing is: none of this is gone. Nothing about the web has changed that prevents us from going back. If anything, it's become a lot easier. _We can return._ Better, yet: we can restore the things we loved about the old web while incorporating the wonderful things that have emerged since, developing even better things as we go forward, and leaving behind some things from the early web days we all too often forget when we put on our rose-colored glasses.
- url: https://www.collectorsweekly.com/articles/the-polyamorous-christian-socialist-utopia-that-made-silverware-for-proper-americans/
name: "The Polyamorous Christian Socialist Utopia That Made Silverware for Proper Americans"
summary: |
The fascinating origins of Oneida silverware.
- url: https://www.experimental-history.com/p/excuse-me-but-why-are-you-eating
name: "Adam Mastroianni: Excuse me but why are you eating so many frogs"
summary: |
> I think the devil is real and he wants you to be more productive. Hes everywhere,
> spreading wickedness disguised as wisdom.
>
> ...
>
> For legal reasons, Im not saying the people who write this stuff are literally
> Lucifer in human skin. Its just that, if I wanted to maximize human misery, I
> would 100% try to convince people to spend more time doing things they hate.
- url: https://en.m.wikipedia.org/wiki/The_bezzle
name: "Concept: The Bezzle"
summary: |
> The bezzle is a term originally coined by John Kenneth Galbraith for a long-term
> pattern of bad faith in which the mark does not realise at the time that they
> have been a victim, and may even feel that they have gained in the short term,
> until being disillusioned later on. The term is a contraction of the word
> "embezzlement". The bezzle does not necessarily require criminal acts; the creation
> of illusionary wealth suffices.
I think we're living in the bezzle.
- url: https://xeiaso.net/shitposts/no-way-to-prevent-this/CVE-2024-1086/
name: >
"No way to prevent this" say users of only language where this regularly happens
summary: |
> In the hours following the release of CVE-2024-1086 for the project The Linux kernel, site reliability workers and systems administrators scrambled to desperately rebuild and patch all their systems to fix a vulnerability that allows an attacker with unprivileged command execution to gain read/write access to page tables. This is due to the affected components being written in C, the only programming language where these vulnerabilities regularly happen. "This was a terrible tragedy, but sometimes these things just happen and there's nothing anyone can do to stop them," said programmer King Bud Hodkiewicz, echoing statements expressed by hundreds of thousands of programmers who use the only language where 90% of the world's memory safety vulnerabilities have occurred in the last 50 years, and whose projects are 20 times more likely to have security vulnerabilities.
- url: https://amycastor.com/2023/09/12/pivot-to-ai-pay-no-attention-to-the-man-behind-the-curtain/
name: "Pivot to AI: Pay no attention to the man behind the curtain -- by Amy Castor and David Gerard"
summary: |
> The magical claim of machine learning is that if you give the computer data, the computer will work out the relations in the data all by itself. Amazing!
>
> In practice, everything in machine learning is incredibly hand-tweaked. Before AI can find patterns in data, all that data has to be tagged, and output that might embarrass the company needs to be filtered.
>
> ...
>
> Commercial AI runs on underpaid workers in English-speaking countries in Africa creating new training data and better responses to queries. Its a painstaking and laborious process that doesnt get talked about nearly enough.
>
> AI doesnt remove human effort. It just makes it much more alienated.
- url: https://allpoetry.com/poem/14374597-The-Homework-Machine-by-Shel-Silverstein
name: "Shel Silverstein: The Homework Machine"
summary: |
It appears that Shel Silverstein predicted ChatGPT all the way back in 1981.
- url: https://fromjason.xyz/p/notebook/any-technology-indistinguishable-from-magic-is-hiding-something/
name: "Jason Velazquez: Any Technology Indistinguishable From Magic is Hiding Something"
summary: |
> I cant stress this point enough. The reason why GAMM and all its little digirati minions on
social media are pushing things like crypto, then the blockchain, and now virtual reality and
artificial intelligence is because those technologies require a metric fuckton of computing
power to operate. That fact may be devastating for the earth, indeed it is for our mental health,
but its wonderful news for the four storefronts selling all the juice.
- url: https://en.wikipedia.org/wiki/Gunpei_Yokoi#Lateral_Thinking_with_Withered_Technology
name: "Concept: Lateral Thinking with Withered Technology"
summary: |
> [Gunpei Yokoi, long-time Nintendo designer and producter,] said "The Nintendo
way of adapting technology is not to look for the state of the art but to utilize
mature technology that can be mass-produced cheaply." He articulated his
philosophy of "Lateral Thinking of Withered Technology" (枯れた技術の水平思考,
"Kareta Gijutsu no Suihei Shikō") (also translated as "Lateral Thinking with
Seasoned Technology"), in the book Yokoi Gunpei Game House. "Withered technology"
in this context refers to a mature technology which is cheap and well understood.
"Lateral thinking" refers to finding radical new ways of using such technology.
Yokoi held that toys and games do not necessarily require cutting-edge technology;
novel and fun gameplay are more important. In the interview, he suggested that
expensive cutting-edge technology can get in the way of developing a new product.
ht [Simon Willison](https://simonwillison.net/2024/Mar/14/lateral-thinking-with-weathered-technology/).
- url: https://coryd.dev/posts/2024/look-for-longevity/
name: "Cory Dransfeldt: Look for longevity"
summary: |
> Everyone has a list of products they've seen fail and disappear or get acquired
and disappear. I want a less-ambitious, lower-scale, bootstrapped company with a
plan. I love solo founders with low costs and a fair subscription price.
_Yep_. What deranged times we live in that it is routine not only for businesses
to launch with no plan for ever generating a sustainable income, but for those
businesses to rake in buckets and buckets of investment.
- url: https://chaos.guru/essays/2024/hostile-environments/
name: "Luka Kladaric: Shipping quality software in hostile environments"
summary: |
A harrowing tale of fixing an unsustainable software project. I've been there.
After being there, I agree with one of Luka's takeaways-- you cannot wait for
permission to fix maintainability problems in software. You have do it. And if you
have to do it quietly and subvert "the process" to make it happen, do it anyway.
- url: https://pando.beehiiv.com/p/javascript-was-slowing-me-down-all-in-on-elixir
name: "Roberto Pando: Javascript was slowing me down. All in on Elixir"
summary: |
I love to hear these kind of stories about adopting Elixir. I went through a similar
arc when I moved from Python/Django, to Node, to Ruby/Rails, and finally to Phoenix/Elixir.
- url: https://darthmall.net/weblog/2023/rss/
name: "Evan Sheehan: RSS?"
summary: |
There's a swing back to RSS right now, which I think is good. But I also think that Evan's
thoughts here are good. RSS can't be the only solution for how we take in the web. It can't
be the only solution for how we decentralize the web again.
Hat tip to [Greg Morris](https://gregmorris.co.uk/2024/01/29/visit-more-blogs) for his related
post that helped me find this one.
- url: https://ethanmarcotte.com/wrote/generative/
name: "Ethan Marcotte: Generative"
summary: >
A collection of quotes about AI from 1683 to 2024.
- url: https://seldo.com/posts/ai-ml-llms-and-the-future-of-software
name: "Laurie Voss: On AI, ML, LLMs and the future of software"
summary: >
A level-headed explanation of what exactly AI, ML, and LLMs are. "LLMs are really complex markov
chains; but the really complex part makes them qualitatively different" has been by go-to
explanation of LLMs. I disagree, however, with the idea that LLMs "understand" anything. LLMs
contain big statistical models of sentence and paragraph structure, and of the relationship
between words and phrases. This allows them to generate text that is more of a statistical match
for text written by humans. That humans see this as "understanding" is a form of pareidolia.
This distinction is narrow, but important.
- url: https://coryd.dev/posts/2024/towards-a-quieter-friendlier-web/
name: "Cory Dransfeldt: Towards a quieter, friendlier web"
summary: >
A series of great principles for a better web! Hear, hear!
Side note: thanks to Cory for inspiring me to add a link log feed to this site,
inspired by his at coryd.dev.
- url: https://www.abstractmachines.dev/posts/am013-easy-to-write-code-considered-harmful/
name: "Leandro Ostera: AM013 Easy-to-Write Code Considered Harmful"
summary: >
Leandro argues that the key to writing readable code is taking implicit context
and making it explicit. I agree!
This is also one reason I love Elixir. Many of the design choices in the language
and standard library encourage you to explicitly write what you mean-- even if it
is more keystrokes.
- url: https://soatok.blog/2024/02/27/the-tech-industry-doesnt-understand-consent/
name: "Soatok: The Tech Industry Doesn't Understand Consent"
summary: >
A brilliant lens for thinking about our relationship with tech products, design,
and terms of use. Opt-out "consent" isn't consent at all. "Maybe Later" isn't
consent either.

View file

@ -1,15 +0,0 @@
---
date: 2018-12-06
title: About Me
slug: index
---
My name is Robert Prehn.
I'm a software engineering leader and independent consultant. You can hire me to help your software team to ship products better and faster. I'm also a Worker-Owner at [Mythic Insight](https://www.mythicinsight.com/).
A better future is possible!
<p class="h-card">
<a class="p-name u-url" href="https://pre.hn" target="_blank">Robert Prehn</a> | <a class="u-key" href="https://keybase.io/prehnra/pgp_keys.asc" target="_blank">Public Key</a> | <a href="https://github.com/prehnRA" rel="me" target="_blank">GitHub</a> | <a href="https://keybase.io/prehnra" rel="me" target="_blank">Keybase</a> | <a href="https://mastodon.social/@prehnra" rel="me" target="_blank">Fediverse</a>
</p>

View file

@ -1,49 +0,0 @@
---
title: The PERMA Model
date: 2019-02-20
slug: what-is-the-perma-model
---
The PERMA model is a theoretical model of wellbeing designed by Martin Seligman as part of a branch of psychology known as "positive psychology." I originally ran across it as part of [The Science of Well-Being](https://www.coursera.org/learn/the-science-of-well-being) course that I took last year. Seligman and others designed PERMA as a simple, but scientifically-validated model for understanding well-being and happiness. People use the PERMA model in their day to day lives to think about, and improve, their well-being. It is also used in research on well-being in positive psychology.
PERMA is an acronym and each letter represents one of the components of the model:
- <strong>P</strong>ositive Emotions
- <strong>E</strong>ngagement
- <strong>R</strong>elationships
- <strong>M</strong>eaning
- <strong>A</strong>chievement
**Positive Emotions.** Clearly, positive emotions are strongly connected to happiness. In this case, positive emotions specifically means feel joy, positivity, and contentedness.
**Engagement.** Engagement means how often you become absorbed in what you are doing and lose track of time. Research shows that getting into a "flow" state when working or doing a hobby leads to a feeling of satisfaction.
**Relationships.** Our connection to other people also drives our feeling of well-being. Our feeling that people love us and support us contributes to our feeling of well-being.
**Meaning.** We want to feel like the things we are doing matter and that we have a purpose.
**Achievement.** A feeling that we have, make progress to, and achieve our goals contributes to our sense of well-being.
Psychologists have experimentally shown that each of these five components materially correlates with well-being and happiness.
The PERMA model is also the basis for the PERMA Profiler, which assesses these factors as a numerical score. This is useful because we can use this score to quantitatively track well-being. We can do experiments to see which other techniques and factors might influence well-being.
## How to calculate the PERMA Profiler score
Julie Butler and Margaret L. Kern developed the PERMA Profiler as a brief way to measure the PERMA factors and other factors in general well-being.
The PERMA Profiler is a 23 question survey. It includes 3 questions for each of the five PERMA categories (15 PERMA questions), plus 3 questions on negative emotion, 3 questions on health, 1 question on loneliness, and 1 question on general sense of well-being. We rate each question on a relevant 0 to 10 scale-- for example "0 Never to 10 Always" or " 0 Terrible to 10 Excellent." To calculate the PERMA Profiler overall well-being score, you average the 15 PERMA questions and the general well-being question. The other seven questions disrupt answering tendencies, which makes the answers more accurate. They also record other information relevant for positive psychology researchers.
Research psychologists have been experimentally validated the PERMA Profiler measure in several different contexts. They have also compared and correlated the PERMA Profiler to a lot of other measures of well-being. If you'd like to read [the original paper it is freely available here.](http://internationaljournalofwellbeing.org/index.php/ijow/article/download/526/579)
## My Experience With PERMA and the PERMA Profiler
I'm a person who has to apply a lot of techniques to regulate my mood and my energy levels. PERMA feels like it correlates well to how I feel on any given day. This makes it useful for self-experimentation and has part of my self-evaluation of my feelings.
As I said, I first learned about PERMA through [The Science of Well-Being](https://www.coursera.org/learn/the-science-of-well-being) course that I took last year. Throughout the course, I took the PERMA Profiler every week and made note of my score each time. I also made notes about my emotional and physical health at the time I took the PERMA survey. In my experience, PERMA does a fairly good job of mirroring my feelings of well-being or lack thereof. On my worst days, I'll score a 4.5 out of 10. My best days are an eight. My most typical score is around a seven these days.
I created the PERMA profiler as a Google Form. Since the summary score is just an average of 16 of the 23 questions, it was easy to compute. This format makes it easy for me to compare the results to other factors, like how many tasks I do in Todoist or whether I checked off my habits in Habitica.
I've found it useful as a data point I can measure about myself and compare with other factors. Does PERMA go up when I exercise? Does it go down when I have a lot of meetings? Or alternately, am I more likely to stick to my positive habits if my PERMA score is high?
I recognize that I've gamified this well-being score. I realize that by knowing about how the score works, I may be influencing my results. I can't say for sure that this attention I'm placing on the number isn't distorting my results. I worry that I'm putting pressure on myself to increase the _score_, rather than well-being. But I _can_ say that I feel better and that's the point.','5 Factors for Well-Being. What is the PERMA model?','There are 5 factors which have been scientifically shown to drive our sense of well-being and happiness. Learn what they are and how to apply them through the PERMA Profiler.

View file

@ -1,64 +0,0 @@
---
title: Minimal Phoenix and Elixir Dockerfile Example
---
Recently, I was setting up a Dockerfile for a Phoenix web app. There are official **Elixir** Docker images, but finding one specifically set up to handle the Phoenix Framework with asset compilation is messier territory. There's no single set of "official" configurations.
Everybody has an opinion about how you should do this. A lot of these opinions involve adding a lot of bells and whistles. For one, their preferred solution might include Docker Compose. For another, Distillery releases. Since I had not successfully deployed my app with Docker yet at all, I wanted fewer variables to debug.
Here's what I came up with:
```dockerfile
FROM elixir:1.8.0-alpine
#### If needed for native dependencies
RUN apk add --no-cache make gcc libc-dev
ENV CC=gcc
ENV MAKE=cmake
#####
RUN mix local.hex --force \\
&& mix local.rebar --force
WORKDIR /root/app
ADD ./ /root/app/
EXPOSE 4000
ENV MIX_ENV=prod
ENV PORT=4000
RUN mix deps.get
RUN mix deps.compile
RUN mix compile
RUN mix phx.digest
CMD ["mix", "phx.server"]
```
This starts with the elixir alpine image. Alpine is a skinny Linux that works well in containers. I've found that it is a suitable base for Elixir apps. In my case, I needed a C toolchain to compile some libraries. You might not need that part. Then it sets up hex and rebar for fetching and building dependencies. Then it adds the application directory. It sets the default port and environment. It fetches the dependencies, compiles them, compiles the app, and digests the assets. Then, it starts the server. That's it.
This approach follows the minimal instructions for a production Phoenix deployment on Docker, with no extras. From there, you can add ~complexity~ more features if you would like.
## Bonus: .dockerignore for Phoenix and Elixir Projects
Here's the .dockerignore file I use:
```
.git
Dockerfile
# Build artifacts
_build
deps
*.ez
# Crash dumps from Erlang VM
erl_crash.dump
# NPM dependencies added by asset pipeline
node_modules
```

View file

@ -1,29 +0,0 @@
---
title: "Elixir Programming Language and the Phoenix Framework: What can you build with them?"
---
You can use the Elixir programming language to build anything that you can build in any other programming language. It has a great framework for web applications called [Phoenix
](https: //phoenixframework.org/). It can be used in embedded systems— see [Nerves](https://github.com/nerves-project/nerves). It can be used for anything in between.
When people ask [what Elixir can be used for](https://www.quora.com/What-is-Elixir-programming-language-used-for), (or [here](https://www.amberbit.com/blog/2018/5/15/when-to-use-elixir-language/)) the common replies are “chat servers”, “telecomm switches”, or “APIs.” I think the reason these are the common replies is that Elixir really shines in areas where you need to handle very high volumes, have high reliability, and do real-time or near-real-time communication. And Elixir is good for those cases, but it also excels as a language for making systems that dont need to handle huge traffic or real time communication.
Phoenix, as a framework, can essentially do everything Rails, Django, Laravel, or Spring can do. It has models (ok, schema structs), views, and controllers. In my experience, it has some serious advantages over Rails, Django, Laravel, or Spring. For one, yes, it is faster. Responses come in microseconds, not seconds or milliseconds. To me, thats not the most important thing. Whats more important: the architects of Phoenix learned from the missteps of those other frameworks. Phoenix and [Ecto](https://hexdocs.pm/ecto/Ecto.html) (the persistence wrapper) made better choices.
To cherry pick one example: in Ecto, you have to explicitly say which related data you want fetched from the database. In ActiveRecord and Rails, if you miss a join, Rails will just load the related records when you need them. That sounds great until you put it into a loop. Rails will quietly and diligently ping your database with many queries in a row, fetching one extra record at a time. Ecto instead asks you: “Hey, did you want this? Because you didnt ask for it.” It forces you to be clear, and in forcing you to be clear, it can be efficient.
To pick another example: in Phoenix, your entire request-to-response circuit is just a series of functions, output from one piped as input to the next. Each receives a connection and returns a connection which may or may not be different. Most of those functions sit directly in your application source code. The ones that dont are clearly invoked from within your source code. Need to add a new junction in the chain? You go into your code and add the junction. This is how Plug works. In Rails, most of the processing of requests and responses is hidden. It lives within the Rails framework code. To modify it, you better hope that the designers of Rails left an appropriate config variable or lifecycle callback. Otherwise, you just have to “patch” Rails in memory. And you better hope that you patch the right spot and that the patch loads correctly. If the Rails team renames the methods or classes that you patched— your patch falls off and your application breaks.
So, what can you use Elixir for? What can you use Phoenix for? I personally use it for everything unless I have a good reason not to. Its been a long time since Ive had a reason to use something else.
## Bonus Q&A: Ok, but what have you built in Elixir?
Me and my team have built, with Elixir:
- An incentive platform for software developers
- Tons of business workflow automation and management software for several industries
- Real estate tools
- Event booking software
- Local business directories
- Content management systems
- Customer relationship management software
- Chat bots

View file

@ -1,29 +0,0 @@
---
title: This Weekend I Read… (2019-03-25)
slug: twir-2019-03-25
---
Here are some interesting (and sometimes scary) things I read this weekend:
## Facebook Content Reviewers Have A Hellish Job
Content reviewers at Facebook are constantly subjected to horrifying videos of violence, racism, and conspiracy theories, and they arent being given the support they need. Some might wave this off as “the nature of the job,” but I think like anyone in a hazardous job they should be given the right support structure, safety equipment, and hazard pay. Instead, the moderators (who are outside contractors) are paid far less than the average Facebook employee, and are subjected to a high pressure environment where they watch 2,
400 traumatizing videos in an 8 hour shift (4 per minute) and managers time their bathroom breaks.
- [Some Facebook content reviewers in India complain of low pay, high pressure
](https: //www.reuters.com/article/us-facebook-content-india-feature-idUSKCN1QH15I) (Munsif Vengattil, Paresh Dave @ Reuters)
- [THE TRAUMA FLOOR: The secret lives of Facebook moderators in America](https://www.theverge.com/2019/2/25/18229714/cognizant-facebook-content-moderator-interviews-trauma-working-conditions-arizona) (Casey Newton @ The Verge)
## The Real Reason for the 40 Hour Work Week
David Cain, writing at his blog Raptitude (“Getting better at being human”), puts forward an interesting theory about why we still have the 40 hour work week even though [the average office worker is productive only 3 hours a day](https://www.inc.com/melanie-curtin/in-an-8-hour-day-the-average-worker-is-productive-for-this-many-hours.html) and [productivity has been steadily increasing in the years since the 40 hour work week was won](https://en.wikipedia.org/wiki/Real_wages#/media/File:US_productivity_and_real_wages.jpg). His theory: it isnt about labor supply, but instead it is about the demands for goods and services. Tired, time-constrained workers want more creature comforts, and buy more convenience items (fast food). They also prefer hobbies which take less time and energy, but more money (e.g. TV, movies, fast fashion) over hobbies which are cheap or free, but time consuming (e.g. reading, gardening, DIY crafting). His anecdotal observations which are woven throughout— such as developing a habit for expensive takeaway coffee after getting a new high-stress job— jive with my experience as well.
- [Your Lifestyle Has Already Been Designed](https://www.raptitude.com/2010/07/your-lifestyle-has-already-been-designed/) (David Cain @ Raptitude)
## The Life Changing Magic Manga of Tidying Up
Did you know that there is a [graphic novel](https://smile.amazon.com/dp/0399580530/) version of Marie Kondos The Life Changing Magic of Tidying Up? Its a fast read (about 180 pages, mostly pictures) and it is overflowing with charm and wholesome energy. I think it could serve either as a good introduction to the KonMari technique or as a quick refresher.
- [The Life Changing Manga of Tidying Up @ Amazon](https://smile.amazon.com/dp/0399580530/)

View file

@ -1,298 +0,0 @@
---
title: Setting up CI/CD for Docker and Kubernetes Using Drone
---
I have been a Travis CI user. However, Travis has gotten less reliable for me lately. On top of that, I have qualms about how the acquisition of Travis by Idera, and the subsequent layoffs, were handled. Travis is also a square peg in the octagonal hole of my Kubernetes environment. It is a hosted, external service. Everything else I use to develop my applications is hosted inside of my cluster. My Docker registry and my gitops operator run in my cluster. My databases are in my cluster. My storage provider and object store run in cluster. My apps run in cluster. Why would I run my CI/CD service outside of the cluster?
I came across Drone in my research about alternatives. Drone is a fully container-native, container-loving CI solution. It's Docker all the way down. Since my application is already "Dockerified", my hosting environment is all Docker all day, and my deployments are already in the form of a Docker push, why not do CI/CD in Docker as well?
Drone is basically a small framework for running CI jobs made of docker containers. You build your pipeline as a series of steps, each of which is a docker base image, some configuration, and your test commands. Drone also has all the standard integrations you would expect for a CI service-- it talks to GitHub, GitLab, Bitbucket, and more.
To use Drone, you'll have to embrace the Docker way. Let go of your test scripts that are building everything from a ubuntu image or a language version manager. Let go of the "special case magic" way DBs and other supporting services are handled in other CI platforms. In exchange, you'll find that Drone will let you use any language, any tools, and any languages, so long as they have a Docker image.
## Drone Setup on Kubernetes
I followed [this official (but experimental) guide](https://docs.drone.io/installation/github/kubernetes/) for setting up Drone on Kubernetes.
Here's the configuration I used for Kubernetes:
```
---
apiVersion: v1
kind: Namespace
metadata:
name: drone
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
labels:
app: drone
name: drone
namespace: drone
spec:
replicas: 1
template:
metadata:
labels:
app: drone
name: drone
namespace: drone
spec:
containers:
- name: drone
image: drone/drone:1.0.0
env:
- name: DRONE_KUBERNETES_ENABLED
value: "true"
- name: DRONE_KUBERNETES_NAMESPACE
value: "drone"
- name: DRONE_GITHUB_SERVER
value: "https://github.com"
- name: DRONE_GITHUB_CLIENT_ID
value: "REDACTED"
- name: DRONE_GITHUB_CLIENT_SECRET
value: "REDACTED"
- name: DRONE_RPC_SECRET
value: "REDACTED"
- name: DRONE_SERVER_HOST
value: "REDACTED.example.com"
- name: DRONE_SERVER_PROTO
value: "https"
- name: DRONE_USER_FILTER
value: "prehnRA"
- name: DRONE_USER_CREATE
value: username:prehnRA,admin:true
- name: DRONE_DATABASE_DRIVER
value: postgres
- name: DRONE_DATABASE_DATASOURCE
valueFrom:
secretKeyRef:
name: drone-postgres-url
key: url
ports:
- containerPort: 80
- containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
labels:
app: drone
name: drone
namespace: drone
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: drone
type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/tls-acme: "true" # enable certificates
certmanager.k8s.io/cluster-issuer: letsencrypt
kubernetes.io/ingress.class: "nginx"
labels:
app: drone
name: drone
namespace: drone
spec:
rules:
- host: REDACTED.example.com
http:
paths:
- backend:
serviceName: drone
servicePort: 80
path: /
tls: # specify domains to fetch certificates for
- hosts:
- REDACTED.example.com
secretName: drone-tls
---
apiVersion: kubedb.com/v1alpha1
kind: Postgres
metadata:
name: drone-postgres
namespace: drone
spec:
version: "10.2-v1"
storageType: Durable
storage:
storageClassName: "rook-block"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 256Mi
terminationPolicy: DoNotTerminate
```
Note that I use kubedb in my cluster, so I am able to request a new Postgres database through Kubernetes configuration YAML. If you don't use kubedb or similar, you'll have to provide a db to Drone differently. By default, Drone uses a sqlite3 database, but this isn't much good in Kubernetes by default, because if you Drone pods get restarted, you will lose your configuration and job history.
I give the Postgres url to Drone via a [Kubernetes secret](https://kubernetes.io/docs/concepts/configuration/secret/#creating-your-own-secrets) called `drone-postgres-url` in the `url` key. This secret must be in the drone namespace. Here's how you can do that:
```bash
echo -n 'YOUR_POSTGRES_URL' > ./url
kubectl create secret generic drone-postgres-url -n drone --from-file=./url
```
## Testing and Deploying An App
The application I wanted to test and deploy through Drone is an Elixir app that is released by semantic-release as a Docker image. I've written previously [on the Revelry blog](https://revelry.co/semantic-release/) about how to do that.
You configure Drone using a .drone.yml file. The main YAML object defined in that file is a "pipeline", which defines a series of steps and services which Drone will use to run your tests and deploy your app.
A basic pipeline for my app might look like this:
```
---
kind: pipeline
name: default
steps:
- name: backend
image: elixir:1.8.0-alpine
commands:
- mix local.hex --force && mix local.rebar --force
- export MIX_ENV=test
- mix do deps.get, deps.compile, compile, phx.digest, ecto.create, ecto.migrate, test
```
There's a problem: my tests won't pass without a working database, and we don't have one yet. In Drone, the way to get a supporting container for something like a database or a cache is via a service. Services are also just a Docker container which runs with a certain configuration. Drone will run them before your steps. Other parts of your pipeline can communicate with services over a network (services are given a hostname that matches their service name) or via a shared volume.
Here's what the same pipeline looks like with a mariadb service:
```
---
kind: pipeline
name: default
steps:
- name: backend
image: elixir:1.8.0-alpine
commands:
- mix local.hex --force && mix local.rebar --force
- export MIX_ENV=test
- mix do deps.get, deps.compile, compile, phx.digest, ecto.create, ecto.migrate, test
services:
- name: cms-database
image: mariadb
ports:
- 3306
environment:
MYSQL_DATABASE: "cms_test"
MYSQL_USER: "REDACTED"
MYSQL_PASSWORD: "REDACTED"
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
```
I also configured my test suite to use a mariadb database at the host `cms-database`, port 3306, with the given username and password.
My tests pass!
Next, I need to add my deployment step. As I mentioned before, this app deploys as a docker image, via semantic-release and semantic-release-docker. In order to do that, I need to use a "docker in docker" image-- which is just what it says, a Docker image containing the Docker daemon and Docker CLI.
It's actually best to use two of these. Drone (and Docker) prefer if any long running services, such as the Docker daemon, run in their own containers. In my experience, trying to run the Docker daemon in the background of a container that is also doing other commands overcomplicates things. Running the Docker daemon in an isolated container works better, because Docker has provided out of the box initialization scripts for that scenario.
Here's the pipeline with both "dind" parts added:
```
---
kind: pipeline
name: default
steps:
- name: backend
image: elixir:1.8.0-alpine
commands:
- mix local.hex --force && mix local.rebar --force
- export MIX_ENV=test
- mix do deps.get, deps.compile, compile, phx.digest, ecto.create, ecto.migrate, test
- name: deployment
image: docker:dind
volumes:
- name: dockersock
path: /var/run
environment:
GH_TOKEN:
from_secret: gh-token
DOCKER_USERNAME: ci
DOCKER_PASSWORD:
from_secret: docker-password
commands:
- apk add nodejs nodejs-npm openssl git
- npm install -g npm
- (cd assets; npm install; npm run deploy)
- npm install
- docker build --network=host . -t REDACTED.example.com/my_repo/my_app
- npx semantic-release
services:
- name: cms-database
image: mariadb
ports:
- 3306
environment:
MYSQL_DATABASE: "cms_test"
MYSQL_USER: "REDACTED"
MYSQL_PASSWORD: "REDACTED"
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
- name: docker
image: docker:dind
privileged: true
network: host
hostNetwork: true
mtu: 1200
volumes:
- name: dockersock
path: /var/run
volumes:
- name: dockersock
temp: {}
```
That's a lot of new pieces. What's going on? Well, we've added a `docker:dind` step to the pipeline. This will run our Docker commands, for building and pushing the Docker image. We also need npm and NodeJS, because semantic-release is a Node package. We install npm and update it to the latest version for good measure. Then `(cd assets; npm install; npm run deploy)` builds my assets for production. `npm install` installs semantic-release and the various plugins I use (see my article from the Revelry blog). I build the Docker image. Then, I run semantic-release. Since I'm using semantic-release-docker, it will login to my Docker repo and push the image.
In order to actually build the image, we need a running Docker daemon. That's where the second `dind` comes in. This one is a service. It runs in privileged mode (required for the dind daemon), which means my Drone project must be flagged as "trusted." We use a shared volume to allow the Docker CLI running in my deployment step to communicate with the Docker daemon running as a service.
I need to provide some credentials for GitHub and for my Docker registry. I do that by exposing them as environment variables. Since I don't want to check in a sensitive credential to git, I use Drone secrets for passwords and tokens. You can set the value of the secret in the project settings UI.
When you put it all together, Drone will do the following sequence:
- Start a mariadb database and expose it on a network
- Start a docker and expose it on a shared volume
- Prepare and run my test suite in an Elixir docker image
- If my tests pass, move on to a deployment phase:
- Build my assets
- Build a Docker image containing my latest code
- Tag the image based on the proper semantic version
- Push that tagged version and `latest` to my Docker repo
- Also, tag that release in GitHub
## Other Drone Features
I had a lightbulb moment while I was working with Drone. I had been wondering things like "I wonder which DBs Drone supports" or "I wonder which languages Drone supports." Then I realized: Drone supports everything that has a Docker image. To me, this makes it a more flexible and powerful tool than a CI architected like Travis or Codeship. In those CIs, you either have to wait for official support for your language (or service), or you have to hack together a working test script from a base intended for a different language or DB. The way Drone does this means that Drone immediately has a "feature list" longer than I can write here.
Beyond this, there are other Drone features worth mentioning:
- Drone supports Agents, which allow you to scale up your CI environment to handle more simultaneous builds. They are small daemons which you deploy to as many servers as you want. Each agent receives orders from the central Drone server which dispatches builds.
- Drone supports multiple secrets plugins. In my example, I used secrets stored in Drone's backing DB, but Drone also supports Vault and Kubernetes secrets, among others.
- In addition to GitHub, Drone supports GitLab, Gitea, gogs, and Bitbucket.
- `drone exec` is a cool feature on the Drone CLI which lets you run a build locally on your laptop, using the same configuration.
The only real issue that I hit along the way is that I could not get Drone to accept an encrypted secret from the `.drone.yml` file. Supposedly, Drone supports encrypting secrets via the CLI and including the encrypted version in your `.drone.yml`. I could not get that to work. I had to use the database secrets method instead.
## The Future of Drone
After experimenting with Drone, I think we're going to see it get a lot of traction. It's such a powerful tool, and it so well leverages the Docker ecosystem, that I can't help but think that it is the future of CI.','Setting up CI/CD for Docker and Kubernetes Using Drone | Robert Prehn','Drone is a CI/CD framework that is all in on Docker. In this article, I will describe how I switched my application off of Travis CI, and onto a container-native CI using Drone, Docker, and Kubernetes.

View file

@ -1,47 +0,0 @@
---
title: This Weekend I Read… (2019-04-14)
slug: this-weekend-i-read-2019-04-14
---
# Amazon Workers Have a Hellish Job
> With her job at Amazon, she hoped she could work and pursue an education at the same time. For years, the 27-year-old English major had taken other short-term warehouse jobs—mostly for retail companies, including the shoe store Zumiez. 
> More than two years later, injuries to her shoulder, neck, and wrist sustained during her time at Amazon—lifting up to 100 items an hour, moving them to conveyor belts, and then hauling them into trailers—have made it nearly impossible for her to type without the aid of voice dictation software.
> Between 2015 and 2018, OSHA reported 41 “severe” injuries resulting in hospitalization, including six amputations and 15 fractures, associated with Amazon delivery or fulfillment jobs. 
Amazon workers are receiving severe, life-changing injuries on the job, and Amazon is covering it up using a system of in-house "clinics", complicit company-mandated doctors, and missing OSHA filings.
Who doesn't think Amazon workers suffering through this should have a union? Well, Amazon for one. The company is using old-school union-busting tactics to single out and remove pro-union workers.
- [She Injured Herself Working at Amazon. Then The Real Nightmare Began.](https://www.motherjones.com/politics/2019/03/amazon-workers-compensation-amcare-clinic-warehouse/) by Tonya Riley at Mother Jones
- [Amazon and Union at Odds Over Firing of Staten Island Warehouse Worker](https://www.nytimes.com/2019/03/20/business/economy/amazon-warehouse-labor.html) by Noam Scheiber at NYT
- [Amazon lobbies to exempt employees from labor protections](https://apnews.com/5c01ffdd9fbb48639fc43bc376f501e4) by Tom Janes at AP
- [The Relentless Misery of Working Inside an Amazon Warehouse](https://onezero.medium.com/relentless-com-life-as-a-cog-in-amazons-e-tail-machine-d46b3ef05eb8) by Cameron Brady-Turner at Medium
- [Colony of Hell: 911 Calls From Inside Amazon Warehouses](https://www.thedailybeast.com/amazon-the-shocking-911-calls-from-inside-its-warehouses?ref=home) by Max Zahn, Sharif Paget at The Daily Beast ("Warning: This story addresses suicidal threats by Amazon employees.")
# Meritocracy is Still Fake
Belief in meritocracy is a core part of our modern ideology, particularly in the tech industry. Unfortunately, meritocracy is a false idea that does not exist. Worse, research shows that believing in meritocracy makes you more selfish, less self-critical, and more prone to acting in discriminatory ways.
> Although widely held, the belief that merit rather than luck determines success or failure in the world is demonstrably false. This is not least because merit itself is, in large part, the result of luck. Talent and the capacity for determined effort, sometimes called “grit,” depend a great deal on ones genetic endowments and upbringing.
> This is to say nothing of the fortuitous circumstances that figure into every success story. In his book Success and Luck, the U.S. economist Robert Frank recounts the long-shots and coincidences that led to Bill Gatess stellar rise as Microsofts founder, as well as to Franks own success as an academic. Luck intervenes by granting people merit, and again by furnishing circumstances in which merit can translate into success. This is not to deny the industry and talent of successful people. However, it does demonstrate that the link between merit and outcome is tenuous and indirect at best.
> According to Frank, this is especially true where the success in question is great, and where the context in which it is achieved is competitive. There are certainly programmers nearly as skilful as Gates who nonetheless failed to become the richest person on Earth. In competitive contexts, many have merit, but few succeed. What separates the two is luck.
- [Meritocracy doesnt exist, and believing it does is bad for you](https://www.fastcompany.com/40510522/meritocracy-doesnt-exist-and-believing-it-does-is-bad-for-you)
# We Get to Decide What Comes Next
We're living in interesting times. I think there's pressure building up on one of those socio-political-historical fault lines. We might live to see humanity evolve into its next political and economic model. This can be daunting, but it should also be exciting. After all, if we play our cards right, we can determine what this new model will be.
While I don't agree with the authors entirely, [this article](https://www.fastcompany.com/40454254/dont-be-scared-about-the-end-of-capitalism-be-excited-to-build-what-comes-next) gives much food for thought on this idea. It is likely that what comes next won't be any of the old models, and won't be accurately predicted by any futurist.
Where their argument falters is that they seem to assume that which of these models will emerge is a function of which one best addresses the challenges of the modern era, climate change, and the pressures of automation. That's not how economies change. Economies change as a function of who holds economic power, those people's interests, and how people generally relate to economic activity. Without radical economic democracy which places power in many hands, whatever comes next will only serve the few who currently hold power.
Though I do have to give a special shout-out for introducing me to the term "doughnut economics."
- [Dont Be Scared About the End of Capitalism—Be Excited to Build What Comes Next](https://www.fastcompany.com/40454254/dont-be-scared-about-the-end-of-capitalism-be-excited-to-build-what-comes-next) by Jason Hickel and Martin Kirk at Fast Company

View file

@ -1,17 +0,0 @@
---
title: Cybertruck Is the World's First Ecofacist Vehicle
---
Elon Musk and Tesla recently unveiled Cybertruck. Im sure you know this. Its been everywhere. It is the ride that launched a million memes.
I think Cybertruck held the internets attention so intensely because no one knows what to think about the damn thing. What are we to make of a truck that has an all-electric powertrain while also having ballistic glass windows? What are we to make of a vehicle with cold-rolled steel armor plates and a pop-up tent for camping?
Who is this for? It defies the traditional American left-right analysis. Is it for liberal hippies because of the lithium battery banks? Is it for the red-state, rolling-coal, lifted F250 crowd because of the armor and tank-like styling? This is a small mundane demonstration that politics have never neatly fallen on a one-dimensional spectrum.
I propose that Cybertruck defies the usual auto-industry psychographics (and mainstream-media political analysis), because Cybertruck is the first ecofacist vehicle. Its a car that acknowledges that climate change is real, and that petroleum is not a limitless resource. But rather than ask “How we might avoid the looming climate disaster?”, Cybertrucks designers wondered “How might the wealthy avoid the consequences?” Their answer was “With (nominally) bullet-proof glass and armored door panels.”
Cybertruck nods to climate change while dismissing any collective solutions to the problem. Shouldnt we support public transit? Green public infrastructure programs? Unpaving and sprawl reduction? Reduced consumption? Accountability for the corporations who are ruining the Earth in the first place? “No,” says the Cybertruck. You merely need to purchase a warm armored blanket of individualistic protection. The unworthy (i.e. those who cant afford Cybertruck) will merely perish.
Perhaps Cybertruck draws inspiration from the armored Hilux custom trucks that oligarchs around the world— like Elons apartheid-era afrikaner-mine-owner family— favor for zipping from one fortified holding to another. What are you to do when you are low-key a member of the “law & order” crowd, but you cant be caught pulling up to the gala in anything as gauche as an armored personnel carrier? What are you to do when the gasoline is all gone and your TAG-armored Lexus pulls to an unplanned stop among the hoi polloi?
You can already buy untouchability from almost everything through wealth, but how does one purchase invulnerability from the global apocalypse that you almost definitely had a material role in instigating? Dont worry, Cybertruck will whisk you safely from your winter bunker near Mt. Ruapehu to your summer bunker by Tolaga Bay. You may see the unwashed climate refugees along the highway, but the consequences will never reach you through the ballistic glass.

View file

@ -1,49 +0,0 @@
---
title: Elixir on Heroku with Docker Containers
---
It is possible to deploy your Elixir application on Heroku using the [Elixir Buildpack
](https: //github.com/HashNuke/heroku-buildpack-elixir). However, you may want to deploy using Docker on Heroku instead. Perhaps your application has complex setup or configuration needs. Or perhaps you already have a Docker-ified application and you dont want to have to do extra work to convert it to buildpacks and Procfiles.
Heroku supports Docker via the [Container Registry and Runtime](https://devcenter.heroku.com/articles/container-registry-and-runtime). Heres the process of getting it set up:
1. Create a Heroku application with `heroku create <app_name>`.
2. Set the Heroku stack to “container” `heroku set:stack container`. This enables the container functionality and ensures that Heroku doesnt become confused if your project also contains other manifests (such as package.json or Gemfile).
3. Set up your Docker environment to talk to Herokus Docker registry instead of the default Docker registry: `heroku container:login`.
4. Build the image and push it to the Heroku registry: `heroku container:push web`.
5. Deploy it to your dynos: `heroku container:release web`.
6. Check your site and make sure everything works.
7. If your application does not boot and logs the error message `Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] ** (Mix) Could not find an SCM for dependency :phoenix from <app_name>.Mixfile`, you may have to make a small change to your Dockerfile.
- Add ENV MIX_HOME=/opt/mix before you install hex & rebar in your Dockerfile. The reason this is needed from what I can gather is that Herokus Docker execution environment is different from your local development environment.
For reference, heres my full Dockerfile for my Phoenix application:
```Dockerfile
FROM elixir:1.8.0-alpine
RUN apk add make gcc libc-dev
ENV CC=gcc
ENV MIX_HOME=/opt/mix
RUN mix local.hex --force \\
&& mix local.rebar --force
WORKDIR /root/app
ADD ./ /root/app/
EXPOSE 4000
ARG MIX_ENV=prod
RUN echo ${MIX_ENV}
ENV MIX_ENV=$MIX_ENV
ENV PORT=4000
RUN mix deps.get
RUN mix deps.compile
RUN MAKE=cmake mix compile
RUN mix phx.digest
CMD ["mix", "phx.server"]
```

View file

@ -1,14 +0,0 @@
---
title: "Magic the Gathering: Arena is probably my game of the year"
---
I've been playing Magic the Gathering off and on since 1995. I started out playing with paper cards (it was the only option!), and then briefly played Magic the Gathering Online around 2003. Since then, life changed and I didn't really have time to play. I became a lapsed player.
Last year, I got back into the game in a major way. MTG Arena, the new digital version of Magic, is perfect for me. It's extremely quick and easy to jump in and play a game. And the economy is extremely generous-- if you play consistently, you can get plenty of cards with little-to-no cash investment. And the Magic expansions coming out now are the most interesting and fun the game has been in years.
The community around the game has grown in a great way too. The streamers range from casual entertainers playing off-the-wall decks to the best players in the world streaming their practice sessions. I've even started following along with Magic e-sports and tournament play. In my house, we have favorite pro players!
All-in-all, it's been a great to (re)discover a new old hobby.
<aside><p><i>I'm prehnRA#33926 on MTGA if you want to add me to your friends list.</p></i>
</aside>

View file

@ -1,25 +0,0 @@
---
title: On Capitalist Bread Lines
---
In America, any time someone proposes even modest social democratic reforms,
[some jackass takes to cable TV
](https: //twitter.com/proustmalone/status/1228049815013089280) to warn about the looming danger of socialist bread lines.
So let's talk about bread lines and why they happen.
Visible bread lines happen when a society tries to feed everyone, but can't. People get hungry, but they know that if they go to the grocery and stand in line, they have a chance of getting some bread. No matter who they are or how little money they have, they can stand in the line, and society will at least try to take care of them.
Capitalism has bread lines. They are invisible and omnipresent. You don't see capitalist bread lines because everyone knows that society will make no effort to feed you unless you have money to pay. Why don't people line up for bread at American groceries? Not because they aren't hungry, but because they know it is useless. If you are going to be hungry either way, you might as well save the gas money.
Occasionally, bread lines are allowed to poke through into visibility, so long as they maintain a suitable aesthetic. What are food banks and homeless shelters other than _our bread lines_? Both are evidence of needs unmet. We just consider it acceptable under the guise of "charity," because charity convinces us that the foundation isn't rotten. "Some people just fall through the cracks, but it mostly works," we reassure ourselves.
[37 million Americans don't reliably get enough to eat, including 11 million children.](https://hungerandhealth.feedingamerica.org/understand-food-insecurity/) That's over ten percent of us.
There is another difference between our bread lines and those of the old USSR. Hunger can come from two places: production or distribution.
Bread lines in the USSR were the result of bad harvests. Bad harvests had been a problem in Russia [going all the way back to the tsar](https://en.wikipedia.org/wiki/Russian_famine_of_1891%E2%80%9392). The communists took over a poor feudalist subsistence economy and tried to modernize to stop the cycle of famine. It didn't always work. But they tried to distribute what bread they had to anyone who needed it.
_Our_ bread lines are the result of our distribution. [We make far more food than we need](https://www.pri.org/stories/2013-07-22/millions-hungry-despite-world-food-surplus). We just won't give it to anyone who doesn't have enough money.
Ask yourself which one of these is the greater failure? Is it the country that tries to feed everyone and sometimes fails? Or the country which [throws away its surplus](https://foodforward.org/2017/09/how-much-food-is-wasted-in-america/) rather than feeding those who can't afford to pay?

View file

@ -1,17 +0,0 @@
---
title: One Piece of Work-From-Home Advice That No One Will Give You
---
Since COVID-19 is a serious concern, a lot of companies are asking their employees to work remotely right now. Many of these people have never worked remotely before. Let me tell you, it is different. I've been working from home for about ten years now so let me give you some advice. This time around, I'll skip over the parts about having a desk set aside for your work, making sure to set time boundaries on your work, &c, &c because that's been pretty thoroughly covered elsewhere. I'm going to tell you the part that I haven't seen anyone else say aloud.
You aren't going to feel productive. And it isn't because you are distracted. In fact, it might be because you have fewer distractions!
Allow me to explain. If you are used to working in an office, you are probably accustomed to office chit-chat and doing little laps around the office all day. You talk to the person at the front desk, then to your friend two cubicles down. You get some coffee before you "dive in." Your manager stops by to see how softball went. Someone stops by to say that it is Sylvia's birthday and there is cake in the break room. The guy from facilities needs to stand on your desk to fix that air vent. While he's at it you can't work anyway, so you chat about the Saints. And then you go get that cake, and a coffee refill. You sit down to work, but you stand up again one minute later after you print out that report. You walk to the printer, but your manager catches you on the way and wants to know what you think about the new format for the weekly business unit review. It's getting close to lunch time. &c, &c.
When you work from home your day is different. You are probably trying extra hard to be diligent. You make coffee before your designated start time, because you don't want to be away from your computer if your manager "pings" you. There is no one to chat with on your commute down the hall to your post in the spare bedroom. You might not even have a printer, but if you do, you can reach it from your chair. Your manager doesn't swing by your desk or catch you in the corridor. If they need to talk, they'll schedule a meeting. You eat lunch on a schedule and keep snacks on your desk.
The result of this is a lot less "fluff" in your day. Because you are moving less and talking less, you feel like you are less productive. The truth is, you've probably been getting all your work done in [the three productive hours you actually have every day](https://www.inc.com/melanie-curtin/in-an-8-hour-day-the-average-worker-is-productive-for-this-many-hours.html). I'm not saying this is a bad thing! A lot of people have this revelation after some time working from home and they feel intense guilt about it. I'm telling you it is natural! [Medieval peasants worked about half as much as we do now!](https://groups.csail.mit.edu/mac/users/rauch/worktime/hours_workweek.html). [Hunter-gatherers work about half as much as typical office workers!](http://rewild.com/in-depth/leisure.html) I think we're honestly not built for eight hours of constantly coding or fiddling with reports in a day. We've been fooling ourselves.
I think we all need negative space in our days. We need time to rest and think. It's gauche to admit that in our puritan work culture. We need to be constantly in motion and be seen being constantly in motion. So the average office is a dryer full of ping-pong balls all bouncing off of each other, going round and round, but not making much forward progress. In fact, we're all probably melting a little.
When it is time to work, work hard. Then, embrace the negative space. Rest and think and plan and read. And find time for chit-chat and cake and coffee. Trust yourself and find your rhythm.

View file

@ -1,17 +0,0 @@
---
title: The Corona Recession is Different
---
The Great Recession began as a plague of capital. The Collateralized Debt Obligations and Mortgage Backed Securities got sick first. The real economy got sick later once people couldn't afford to stay in their homes but couldn't afford to sell them either.
Throughout the Great Recession, the working class in general, and service workers in particular, kept everything running&mdash; as they always do. Economists call the Service sector "acyclic" which means it is comparatively resistant to the boom and bust cycles of capitalism. People didn't stop buying haircuts or eating at restaurants during the Great Recession. You still need haircuts, food, and medical care, even if there is havoc in the fictive economy of the stock markets. The Service sector is our life preserver.
The corona recession is a consequence of an actual material plague. People are getting sick first, then the economy is getting sick because people can't show up for work. The Service sector kept us afloat last time, but we need to shut it down for material epidemiological reasons. We are about to be adrift without our life preserver.
Working people make everything: meals, haircuts, medicine and medical care, culture, housing&mdash; everything. For all the emphasis we put on the ups and downs of financial assets, stocks alone have never made anything. We say that capital investment makes the economy move, but it only does so because it commands labor. Without labor, stocks and bonds are inert. A stock has never made you a meal or cared for you when you were sick, and neither has a CEO (putting aside publicity appearances here or there).
This makes the corona recession materially different from the last one. If we don't protect working people through this crisis, we will incur a tremendous human cost. And if the economy is your concern, know that it will _never_ recover unless the working class comes out of this crisis in a strong position. If working people get sick and starve, there will be less food and less medical care as a result. Then _more_ people will get sick and starve. An economic contagion to match the viral contagion.
So what should we do? The tactics we used last time won't work this time. It's debatable whether they worked last time. The government used targeted stimulus to keep the financial, automotive, and real estate industries operating. We _can't_ keep the services sector open. So we need to apply our stimulus directly to working people.
In the short term, we need to get direct cash payments into the hands of every working person in the country. We need that money to stay fed and healthy, which society needs in order to recover when the crisis passes. And long term, we need to make sure working class people share in the prosperity that we create. The risk of this crisis would be far lessened if the working class wasn't in such poor shape to begin with. The working class needs an ownership stake in the economy, savings, and a robust safety net to make it through times like these.','Why the Corona Recession Is Different Than the Great Recession','The Great Recession began as a plague of capital. The corona recession is a consequence of an actual material plague. The tactics we used last time won't work this time. We need to bail out working people and the real economy, not banks and stock markets.

View file

@ -1,65 +0,0 @@
---
title: Will corona recession really kill more people than corona virus? Not unless we're stupid and cruel
---
The question: will corona recession kill more people than corona virus? The answer: not if we take some easy preventative economic medicine.
First, let's do away with the abstractions of economics for a second. People don't die when their bank balance hits zero. It's not some sort of video game life counter. It's not an economic downturn or unemployment _per se_ that kills people. It's starvation, exposure, sickness, and suicide that _actually_ kill people. These "four horsemen" just happen to _correlate_ with economic downturns.
The good news: all of these are thoroughly preventable causes of death, even in an economic downturn. Here's the recommended course of treatment.
## The Plan
### Avoid Starvation.
To prevent starvation, you make sure two things happen: that we make enough food, and that we make sure we distribute it to people who need it. Even in the corona recession, this is not particularly difficult.
- Food production. Firstly, we've been running food surpluses for decades now. In fact, so much so that the government has been holding up food prices by buying up massive "strategic reserves" of food. Reserved for what? Reserved for a situation like this. So we probably don't even need to grow any more corn or wheat this year to avoid starvation. However, we don't even need to stop food production! Only about 7.3 million people in the country are farmers, hunters, fisherpeople, food processors, or grocery workers out of 331 million people in the country. We can avoid any hitch in the food supply by having about 2% of workers keep working and it won't make a dent in social distancing.
- Food distribution. This one is easy. Cut everyone in the country a check for $2,000 a month. People can use that to buy food and pay rent. How do I know we can do that? The cost for this universal basic income (UBI) program would be about $660 billion dollars a month, and we are gearing up to spend $30 trillion _this month_ on Wall Street bailouts.
### Avoid exposure.
We can prevent people from being houseless during this crisis. There are six empty homes for each houseless person. We can prevent a spike in new houselessness by freezing mortgage and rent payments.
We should pass a law that says this: for the next year, mortgage balances are frozen&mdash; no payments are due, no interest will accrue, and no principle will be paid down. Then, in a year, we all pick up where we left off. The only cost of this is the interest that the banks would have been earning otherwise. We could pay off all mortgage interest for about $155 billion dollars a month (way cheaper than those Wall Street bailouts!) or just say "you are welcome for saving you from a foreclosure crisis!" And since landlords won't be paying mortgages, they don't need to collect rent, so we freeze that too.
Or again, we could just cut everyone a month check to cover their payments.
### Avoid sickness.
The most important thing we can do to reduce sickness is keep workers at home if their works is not needed to keep us alive through the crisis! If social distancing is lifted, models predict that 2 million people will die. The options are simple: (1) keep people at home, and there are 90% fewer deaths OR (2) send everyone to work, and two million die.
While we're all here: Medicare for All is cheaper than private insurance. If we're looking for savings, we could save $200 billion per month while making sure that everyone has care! And that's a $200 billion based for a normal month, not per corona month (the savings from M4A increase the more care is demanded)
### Avoid suicide.
Why do you think suicide rates increase in economic downturns? It's because people are hungry, sick, homeless and/or anxious about becoming hungry, sick, or homeless. Solve the others and solve the anxiety about them and you solve the spike in suicide rates. Throw in Medicare for All with access to mental healthcare and lower the rate even further.
## Feasibility
But can we afford it? The UBI would cost $660 billion a month. A mortgage interest freeze costs $155 billion a month, assuming we don't just make banks carry it. Medicare for All _saves_ at least $200 billion a month, probably more in corona times. So our corona recession preventative treatment costs about $600 billion a month. For comparison, the Federal Reserve is about to embark on $30 **trillion** in bank bailouts _in one month_.
On the other side, there's the cost of _not_ preventing the wildfire spread of corona virus. 2.2 million dead according to the latest models. In a normal moral calculus, that should be enough. But let's say you are an economist, and you want to know about the dollar impact, because economists are sociopaths. Normal flu costs about $2.6 million for each person it kills due to lost productivity and medical cost. So if you just linearly scale that to 2.2 million people, it's around $5.7 trillion dollars of impact, which is about 30% of GDP. But flu kills far fewer people than corona does, and epidemics have network effects. A better data point is probably the 1918 flu epidemic. Economic data from 1918 is dodgy, but the areas in the United States which were hit by that year's flu reported 40 - 70% drops in aggregate demand. That's $8.4 to $14.8 trillion in economic cost. **AND TWO POINT TWO MILLION DEATHS.** There. Can I go throw up now?
## Conclusion
Strong social distancing plus strong social safety net _saves_ billions per month and **2 million lives**. There's been a lot of talk of "balance" lately. I propose this: halt non-essential work, and provide a safety net to keep everyone fed, housed, and well. _That's_ the balance we need.
## Sources
- https://www.bls.gov/emp/tables/employment-by-major-industry-sector.htm
- https://www.bls.gov/ooh/production/food-and-tobacco-processing-workers.htm
- https://datausa.io/profile/naics/4451/
- https://www.newyorkfed.org/markets/opolicy/operating_policy_200320a
- https://www.mintpressnews.com/empty-homes-outnumber-the-homeless-6-to-1-so-why-not-give-them-homes/207194/
- https://www.thesimpledollar.com/loans/blog/heres-how-much-the-average-american-pays-in-interest-each-year/
- https://www.washingtonpost.com/health/2020/03/19/coronavirus-projections-us/
- https://www.cnbc.com/2017/10/30/the-flu-costs-the-us-economy-10-point-4-billion.html
- https://www.stlouisfed.org/~/media/files/pdfs/community-development/research-reports/pandemic_flu_report.pdf?la=en
- https://www.latimes.com/business/story/2020-02-14/medicare-for-all-cost
- https://www.imperial.ac.uk/media/imperial-college/medicine/sph/ide/gida-fellowships/Imperial-College-COVID19-NPI-modelling-16-03-2020.pdf

View file

@ -1,27 +0,0 @@
---
title: Notes on Buckminster Fuller's Operating Manual for Spaceship Earth
---
I just finished reading Buckminster Fuller's *Operating Manual for Spaceship Earth*. I've gathered a few of my thoughts on this thought-provoking classic.
My capsule review: The book puts forward a fascinating theory of history and our position in the universe in a concise and engaging package.
As I read the book, my mind kept finding lines between Fuller and eco-socialism or eco-anarchism. While Fuller calls capitalism and socialism "mutually extinct," there are some ideas in his work that wouldn't be out of place in Marx, Proudhon, or certainly Bookchin.
For example: Fuller's Great Pirates theory of history is a first cousin of "the history of man is the history of class struggle." The Great Pirate theory describes the separation of the ruling class from the ruled class based on who labors and who can command labor. Fuller follows this thread through all the mutations of history&mdash; chieftains to kings to industrialists&mdash; until we reach the current epoch. In recent history, the Great Pirates&mdash; the members of the ruling class&mdash; have delegated management of their affairs to states and the scientific-professional class. This is an analysis of our situation that would not be out of place in Piketty.
Fuller correctly concludes that war is a way for the upper class to drive demand and production while controlling the lower classes with xenophobia and violence. He argues that nations and borders are inefficient relics that draw arbitrary unreal lines between people for the purpose of encouraging war and its economic activity. As an engineer, he sees that nations and borders create a tremendous amount of redundancy&mdash; redundancy which is useful if you are a Great Pirate who needs production to continue ceaseless to ensure your continued wealth and power.
Fuller states that if we are to survive long-term, competition between states needs to cease. And since states are not states unless they compete, if we are to survive, states must go.
[I'm starting to understand why Fuller has a lengthy FBI file.](https://paleofuture.gizmodo.com/we-got-buckminster-fullers-fbi-file-1704777475)
People know of this book as an argument for green energy and regenerative systems. Fuller frames Earth as a spaceship with no lifeboats upon which we're hurtling through space. If our species is to live, we need to ensure the continued operation of the life support system that makes our oxygen, water, food, and energy. I know that when the book was written, no one had yet articulated things in this way. It shows the effectiveness of Fuller's ideas and his communication style that these ideas are absolutely everywhere in modern ecology and eco-futurism.
As with all futurism, Fuller's predictive track record is mixed. He predicted that wealth would be essentially limitless and _universal_ at this point. Naturally, as a result, we'd be spending 90% of our day in leisure. This is where lacking a true materialist analysis bites him. Fuller thought we'd either be dead or living without borders by now. He underestimated the ability and desire of the ruling class to adapt to preserve their status. States evolved instead of going extinct.
Fuller couldn't understand why a person with functionally limitless wealth wouldn't start sharing at some point. There comes a point in wealth accumulation when all your barriers are lifted: you have all the creature comforts that you could want, you can travel as much as you would like, and you can work as little as you please. It isn't rational to hoard wealth beyond this point. Fuller, a thoroughly rational person, concludes that the thing to do at that point is to stop seeking further wealth, enjoy what you have, and let the rest flow to everyone else who isn't there yet. He failed to consider that for some people, enough is never enough. Those people seek out wealth, and sometimes they get it. Once they have it, they use their wealth to get more wealth. Since their hunger is infinite, they keep using their wealth to capture more wealth until they have as much as possible, and everyone else is driven to the line of subsistence. The system is inexorable. Even if any individual were to choose differently and give away all their hoarded wealth, another yawning pit of greed would open to fill the gap.
I'm surprised that Fuller missed this, considering he had the Great Pirate theory and whole-systems-thinking right there in the same volume. The Great Pirates keep their fleets because the fleets are power and Great Pirates want power. He spent large stretches of *Operating Manual* discussing how the whole physical world&mdash; galaxy upon galaxy&mash; doesn't constitute a complete system without the metaphysical world of human thought and behavior. The universe acts on us and we act on the universe and then this flow continues round and round forever. If the system of "human ingenuity plus near-limitless solar energy" is generally pointed toward a future of universal wealth and leisure, shouldn't we consider that the human element would nudge the ultimate result one way or the other? We should.
*Operating Manual for Spaceship Earth* gives us a lot to consider in a scant 150 pages. I highly recommend it for anyone interested in considering our position in time and space, in realms physical and metaphysical.

View file

@ -1,7 +0,0 @@
---
title: The Only Way to Wrap an Extension Cord
---
<iframe frameborder="0" scrolling="no" marginheight="0" marginwidth="0"width="788.54" height="443" type="text/html" src="https://www.youtube.com/embed/kda4DPAn3C4?autoplay=0&fs=0&iv_load_policy=3&showinfo=0&rel=0&cc_load_policy=0&start=0&end=0&origin=https://youtubeembedcode.com"><div><small><a href="https://youtubeembedcode.com/de/">youtubeembedcode de</a></small></div><div><small><a href="http://add-link-exchange.com">addlink-exchange</a></small></div></iframe>
You are welcome.

View file

@ -1,7 +0,0 @@
---
title: Developers don't need ping-pong tables.
---
> Unless your goal is to win a ping-pong tournament, remember: when developers change jobs, the last thing they care about is your fancy office and table tennis. Developers need autonomy, mastery, and purpose.
From [Developers Don't Need Ping-Pong Tables](https://sizovs.net/2020/03/26/developers-dont-need-ping-pong-tables/).

View file

@ -1,25 +0,0 @@
---
title: "On \"Time Famine\""
---
I was recently introduced to the concept of ["time famine"](https://www.cnn.com/2017/07/24/health/time-famine-stress-happiness-study/index.html), which is:
> the universal feeling of having too much to do but not enough time to deal with those demands.
I know the feeling. Though the term has been around since 1999 or so, there's been a spike in discussion lately. The focus of that discussion has been on finding ways to save time, mostly via automation products and delivery services. It's almost as if there are people with a vested interest in selling you a "solution" to this problem (whether it works or not). I think most of the discussion and most of the proposed solutions entirely miss the point.
It's natural to look at your todo list and despair. It's _particularly_ natural to despair when you look at your todo list over the span of days, months, and years and never see the numbers tick down. It's _natural_ but it's also _wrong_.
Here's the truth that you don't want to hear: **your todo list will be empty when you are dead**. When are you going to stop doing laundry? When are you going to stop needing to go to the grocery store? When are you going to stop having stuff to do at work? When are you going to stop having to call your landlord or fix things at home? When are you going to stop pursuing your hobbies? When you are dead. Thus, your todo list will be empty when you are dead and not a second before. This is OK.
Your task list isn't a flooded basement, it is a drain pipe. You don't need to be concerned that there is water in there. _That's where the water goes._ You need to be concerned if you are constantly putting more in there than can flow out the other end. Be concerned if the pipes are backing up into the house. Stop having an emotional crisis over the task count in some app. Consider how many things you got done this week, and how many new things you added to the list. These numbers, on a long enough time scale, should be about the same. If you are constantly adding twice as many things to the list as you are checking off, you are going to have a bad time.
By all means, use home automation or a delivery service if it makes you happy. They can be a good way to improve your flow. But if you think of your life as a flooded basement, these things will only ever make you feel like your basement is temporarily less flooded.
How can you stop feeling bad about your task pipeline?
- **Cut yourself some slack.** We're surrounded by pressure to do more. It comes from our bosses, productivity advice sites, our hobbies, and even our families. But you are the only person who can decide that you are doing enough.
- **Say no.** I became much happier after I realized that there were certain hobbies that I can envy from afar, but cannot personally undertake. There are certain social occasions that I wish I could attend, but I simply cannot while keeping my sanity.
- **Embrace an organizational system that is about _flow_, not _zero_.** I'm very partial to David Allen's Getting Things Done methodology, which probably saved me from death by anxiety and depression. That's a big statement and I mean it.
I'm certainly not immune to feeling "time famine." The difference with this mindset and these tools is that I feel it less often. When I do, I notice the thoughts and can quash the anxiety.

View file

@ -1,104 +0,0 @@
---
title: Elixir Patterns for Testing with Mox
---
When I need mocks in my Elixir tests, I prefer to use the [Mox](https: //github.com/dashbitco/mox) library. Mox follows the principle of mocking-by-explicit contract. The mox readme explains it like this:
> 1. No ad-hoc mocks. You can only create mocks based on behaviours
> 2. No dynamic generation of modules during tests. Mocks are preferably defined in your test_helper.exs or in a setup_all block and not per test
> 3. Concurrency support. Tests using the same mock can still use async: true
> 4. Rely on pattern matching and function clauses for asserting on the input instead of complex expectation rules
I've found that this works very well with the overall design of the Elixir language. Elixir developers generally prefer explicitly combining functional pieces over any sort of magical hidden state. Some of the other mocking libraries fiddle with your function definitions behind the scenes. I've found that this makes test code harder to read and debug.
When you are using Mox, I believe that it helps if you follow certain patterns. I've worked on several projects using Mox at this point, and I've seen the pain that can come from not establishing those pattern up front. I will summarize my recommendations briefly here before showing some examples:
1. You should define one facade module which both your application and test code call in almost all cases.
2. The facade module should delegate all its work to either the true adapter or the mock adapter, depending on the environment.
3. One piece of configuration should control which adapter is used, and that configuration should be wrapped up in a nice easy to call function.
To boil that down to only one sentence: your application code should not know or care that you are using Mox. If you find your application code caring that it could be mocked out in a test later, you need a new set of abstractions. In fact, most of your _test_ code shouldn't need to know about the mocks, except where it needs to set function call expectations.
What does the code to do this look like? Let's say your application uses a weather API and you don't want to use the real API in your test suite.
Let's say this is the module your application already has for communicating with the weather API:
```elixir
defmodule Weather do
def current_weather(zip_code) do
# makes a GET request to the API to ask for the current weather in a zip code
end
end
```
We would define a behaviour for a weather adapter:
```elixir
defmodule WeatherBehaviour do
@callback current_weather(binary) :: map
end
```
We would have the Weather module adopt the behavior and we would rename it so that it can serve as our live api adapter. Later, we'll tell our application to use the LiveWeather adapter by default.
```elixir
defmodule LiveWeather
@behaviour WeatherBehaviour
def current_weather(zip_code) do
# makes a GET request to the API to ask for the current weather in a zip code
end
end
```
At this point, we need to create a new Weather module so that all of our application code doesn't explode. Our new Weather module won't do much. It will just delegate down to either LiveWeather, or the mock weather adapter as appropriate for the environment:
```elixir
defmodule Weather do
defdelegate current_weather(zip), to: WeatherApp.weather_adapter()
end
```
and we'll need to define `weather_adapter/0` in our application class:
```elixir
defmodule WeatherApp do
def weather_adapter do
Application.get_env(:weather_app, :weather_api_adapter, LiveWeather)
end
end
```
By default, the application will use LiveWeather. This is good for development and production. However, in the test environment, we need to tell the system to use the mock. In config/test.exs:
```elixir
config :weather_app, weather_api_adapter: WeatherMock
```
And we need to actually define our mock! In test/test_helper.exs:
```elixir
Mox.defmock(WeatherMock, for: WeatherBehaviour)
```
That's all the setup. **Notice that nothing outside of the Weather module and it's configuration changed.** None of our controllers or other contexts were disturbed in the process.
If we want to write a test for a function that uses our Weather API, we need to tell Mox what function calls to expect and what to return:
```elixir
defmodule UserTest do
# standard test boilerplate as before
test "current_weather/1 gives the current weather for the user" do
user = %User{zip_code: "19120"}
WeatherMock
|> expect(:current_weather, fn "19120" ->
# I've heard it is always sunny there
%{"description" => "clear"}
end)
assert %{"description" => "clear"} = User.current_weather(user)
end
end
```

View file

@ -1,8 +0,0 @@
---
title: There Are Only Two Programming Errors
---
There are only two programming errors:
1. Not understanding what your program does.
2. Not understanding what your program is supposed to do.

View file

@ -1,5 +0,0 @@
---
title: Yeah, I Guess You Could Say I'm Into Supplements and Nootropics
---
*pops a children's Flintstones vitamin and a Lexapro, washes it down with black coffee directly out of the carafe*

View file

@ -1,11 +0,0 @@
---
title: On Glass Houses and Stones
---
One of my values, as a person, is to endeavor to never be a person who throws a stone in a glass house. In my experience, I've found that there are two ways to avoid being a person who throws stones in a glass house.
The first is to try, to the best of your ability, to not live in anything nearly so fragile as a glass house.
The second, and perhaps, most important way to avoid finding yourself as a glass-house-stone-thrower is to simply not throw stones. This is especially important if you are not certain, beyond a shadow of a doubt, that you are not living in a glass house. However, I find that there are benefits to not throwing stones even if you are reasonably certain that you find yourself living in a house of brick, stone, concrete, or even conventional stick framing. For one, throwing stones carries a certain risk of injury to one's self and others. For two, there's really no perceptible benefit to throwing stones in most cases. For three, it is simply exhausting.
There are, of course, some glass houses that simply need to be shattered from the outside by a well-thrown stone. This is yet another reason to keep your throwing arm rested and the glass out of your hair.

View file

@ -1,29 +0,0 @@
---
title: The Design of Disasters and the Disaster of Design
---
Yesterday, August 30th, 2021, my wife and I put our 19-month old and our cat onto our kayaks and paddled away from our home and out of our neighborhood. The night before, the rivers around our town exceeded flood stage due to storm surge and rain from Hurricane Ida. We woke to three feet of water surrounding our house on all sides. We paddled up the streets of our neighborhood. We made it out and to our car, which we had stashed on high ground in case just such a thing happened. We handed off the kayaks to strangers who were looking for any way to make it to their homes to assess the damage and retrieve anything that could not be replaced. We made it to Jackson, MS, where we are thankfully high and dry with power and wifi.
Much will be written about Ida in the coming weeks, I'm sure. The levees in New Orleans held against a Category 4 (or maybe 5) storm, a triumph of massive public investment. The power grid utterly failed after decades of looting by our privatized utility companies. Apparently, after billions of dollars of city, state, and federal subsidies and sustained year after year rate hikes, neither of their backup power plants nor any of their eight "modernized" main transmission lines are operational. One wonders who pocketed our money.
But I want to talk about something that is within my own little wheelhouse. Something that hits close to home. I want to talk about how the tech industry utterly failed me and everyone in our region.
At the time I most needed information to know what to do for the safety of my family, it was unavailable to me. And it was unavailable to me for stupid, petty reasons. We had cell service and battery power. However, I was unable to track the path of the storm, receive information about power outages in my area, or determine passable evacuation routes away from the storm.
The outage information page for my electric utility weighs in at 5.1 megabytes. It takes 17 seconds to load over the *broadband* connection from which I write to you. The neighboring electric utility that covers the other half of the region clocks in at 4.8 megabytes and loads a little quicker at 6 seconds. Both refused completely to load over LTE, *which is exactly how you would expect customers to access this information when they need it*.
As of the time of writing, the website of NOLA Ready, the official emergency communication channel for the city of New Orleans, will not load at all. One assumes that it has fallen over under the load of everyone in the New Orleans region trying to access emergency information at the same time— a thing people tend to do during emergencies. Or quite possibly, the server is located somewhere in the city of New Orleans, which has no electricity at the moment. Either way, I feel that there is some lack of foresight here.
NOLA Ready's secondary communication channel, Twitter, is totally useless with anything less than a strong LTE signal. First, you need to load the multiple megabytes of mandatory JavaScript and CSS which Twitter *requires* before loading any content. *Then* you need to load all the cute infographics and videos NOLA Ready has produced to transmit the critical emergency data. It's a hopeless endeavor.
And don't get me started on Slack's app, which is apparently just a very thin wrapper around a very heavy web page— none of which was apparently cached on any device I had with a data connection.
What did work during the storm and the evacuation? An informal solidarity network with zero budget operating in the borrowed bits at the edge of the old cellular voice band. I was able to communicate to friends across the gulf coast and in New York, one 140 byte SMS at a time.
It's not that I miss the days of separate mobile versions of web pages. But those mobile sites were slim and to the point. They were not tarted up with ad trackers and multi-megabyte infographics. We were supposed to replace those with progressive enhancement and progressive web apps. The idea was that you would load the no-frills information first, and then *enhance* it with all the colorful bells and whistles. This completely failed to materialize, at least where it matters most.
"Design" failed us. We need real design. Design that centers users, understands their needs and their context, and builds from there. Instead, we got the kind of mediocre design I despise. Design that centers the most highly paid person in the room and/or advertising networks. Design that centers design for the sake of design. Design as pretty, but vapid, commercial art objects. Design that centers mindless adherence to "best practices" where "best practices" is defined as never-ending user surveillance in the service of "analytics" and "A/B testing."
Ironically, what we need here is *less* sophisticated solutions. Our needs after the storm could have been served by plain old unstyled markup, and clear, concise written emergency communication. Hell, plain text files would work. All served from static file hosting instead of some lumbering beast of an enterprise CMS.
Power is out over here. It works over here. These neighborhoods are flooded. These are dry. These hospitals are operational. These are not. The storm is above Jackson and tracking northeast. Give me some good old `<ul>`s and `<li>`s.

View file

@ -1,7 +0,0 @@
---
title: We Have Armin van Buuren
---
![We Have Armin van Buuren](https://www.dropbox.com/s/adwilchh74aa48d/Screen%20Shot%202021-11-29%20at%209.50.25%20AM.png?dl=1)
So… is this a hostage situation oorrr…?

View file

@ -1,7 +0,0 @@
---
title: Three Things I Like This Week
---
1. I've been digging [Oxide and Friends](https: //oxide.computer/) from [Oxide Computer Company](https://oxide.computer/). Oxide is doing something very difficult-- building completely custom, completely secure (from the 1st instruction) servers. Oxide and Friends is the team chatting about the interesting parts of that monumental challenge. I only understand a fraction of what they are talking about, but it is still fascinating. It makes me wish I had finished my Computer Engineering degree. My favorite episode so far is [the episode about the various circuit boards they've designed both for the server AND as tools to doing their work in the lab.](https://www.youtube.com/watch?v=XmiWIlFvSYs).
2. [omg.lol](https://home.omg.lol/) is a delightful place to "get the best internet address that youve ever had." What that means is that it is a simple and very cute service that provides linktree-style profile pages, email accounts, fediverse accounts, link shortening, and more with one subscription-- all attached to the handle you choose for yourself. You can use their URLs, or attach the service to your own domain.
3. I've been enjoying Becky Chambers's [A Psalm for the Wild-Built](https://bookshop.org/p/books/a-psalm-for-the-wild-built-becky-chambers/15125608?ean=9781250236210). The story follows a tea monk whose life is upended when they meet the first robot anyone has seen seen the robots walked off the job and into the wilderness centuries ago. The robot brings with it a seemingly simple and practically impossible-to-answer question: "what do people need?"

View file

@ -1,8 +0,0 @@
---
title: Three Things I Like This Week (2023-02-03)
---
- The Weakerthans's 2003 album _[Reconstruction Site](https://music.youtube.com/playlist?list=OLAK5uy_n4E9NKbNFgsgJQLZczatKfAodn6SXbWr4)_. One of my intentions for this year is to listen to more complete albums instead of hopping from single to single. I've loved this album since it came out, but I rediscovered it this week after the track _Plea from a Cat Named Virtute_ spontaneously appeared in my brain again. Every single track is good, but the album is even better as a whole.
- Consumer Reports released an app called [Permission Slip](https://www.permissionslipcr.com/) that lets you easily opt-out of data collection and sharing with many companies with a few simple taps. In some cases, you can even request that a company delete your data entirely. They estimate that they've saved their users something like 150,000 hours since launch. Amazing and totally free.
- KeokeN Interactive's [Deliver Us the Moon](https://store.epicgames.com/en-US/p/deliver-us-the-moon) is a sci-fi thriller adventure puzzle game. The Earth has been totally depleted of resources, and humanity's only hope for long-term survival seemed to be a Moon-based fusion reactor and the Microwave Power Transmission (MPT) system. Then five years ago, without any warning or explanation, the lunar colonies stopped transmitting and the MPT failed, blacking out the whole world. You play as a lone astronaut sent on a longshot mission to investigate what happened and bring the MPT back on line. I became aware of this game when a sequel (Deliver Us Mars) was released this week.

View file

@ -1,23 +0,0 @@
---
title: "How I Get Fractional Lead Contracts Without \"Doing Sales\""
---
I am often asked how I find the clients for my Fractional Engineering Lead practice. Here's what I do. It has worked for me for about two and a half years now, but it might not work for you and it might not even work for me a month from now.
I don't do sales. I don't do "lead gen" or "biz dev." I don't even really network in the traditional sense. I also don't have someone to do these things for me.
What I do is I help people. I don't help them so that they give me contracts some day. I help them because I like helping people, particularly other Software Engineers, and I help them because it's the right thing to do.
The other thing I do is I ask people to help me. I don't ask for contracts, because either someone has work that's a good fit for me, or they don't. I ask people to give me advice, to help troubleshoot an issue, or to introduce me to their friends.
Every contract I've ever gotten has been someone who I've helped and/or someone who has helped me. It's usually not anytime close to when we had that first interaction. They usually email me up out of the blue and say "I have / heard about a project, and I think you could help."
When I started working as a Fractional Engineering Lead, I got my first contract from an amazing kind former coworker of mine. I helped her (in a very small way) to get that job, and she helped me fix some HR snags at that company. A couple years later, she heard that I'd lost my job and she connected me to my first incredible client. I don't think I would have the business I have today without her!
Ok, but you probably want some practical steps you can take. That's very reasonable.
1. Join communities where people who do what you do hang out. When they ask for advice or need help solving problems, help them. Volunteer yourself to get on a call. _You must do this in the spirit of genuinely helping and making the community better, or it won't work._
2. Fix bugs in open source software. Particularly fix the bugs that no one else wants to fix.
3. Re-post jobs and the posts of those seeking work. Proactively connect people you know to jobs that are open, and vice-versa.
4. Ask for calls with people you like and respect. Ask for advice, and ask if there's anything you can offer in exchange. If what you need is a contract, be honest. _Hey, I'm trying my hand at consulting, I'd like to have a short call to (1) get your advice (2) tell you what I'm trying to do and see if you know anyone who could benefit._
5. Don't filter people out just because they're "not the target demographic" or whatever. That's sales. If you say to yourself "I shouldn't talk to this person, because they probably don't need my services" then you are doing sales. _Don't sell._ Everyone on this earth needs help, and in my experience, the vast majority of people on this planet want to help others.

View file

@ -1,15 +0,0 @@
---
title: "Things I Like This Week (2023-11-06)"
---
# 1. ooh.directory
[ooh.directory](https://ooh.directory/) is "a collection of 2,084 blogs about every topic." I've really enjoyed finding new blogs that I can put in my RSS reader. I'm sure I never would have found many of these delightful blogs without the directory. I'm particularly enamored with the Random button, which I have pinned in my bookmark bar as my latest digital fidget.
# 2. One Revolution Per Minute
Erik Wernquist's six minute short film [One Revolution Per Minute](https://erikwernquist.com/one-revolution-per-minute) visualizes what the view from the spinning habitat ring of an interplanetary cruise ship might be like.
# 3. Ramen
[This](https://www.youtube.com/watch?v=4poyENnFKm4) 48 second animated short about the iconic japanese dish was rather captivating.

View file

@ -1,16 +0,0 @@
---
title: My Ten Commandments of New Year's Resolutions
---
1. Don't make a New Years resolution.
1. Resolutions must come from self-love, not self-hate.
1. Cut yourself some slack.
1. A New Years resolution must be a commitment to take a physical action with some frequency or no more than a certain frequency. If the movie of your life couldn't commit your New Years resolution to film, it's a concept, a notion, a reckon, not a resolution.
1. Your goal must be no more than double or no less than half of what you did this year. If you read two books last year, your goal this year cannot be to read 100 books. If you drove your car to work instead of biking 150 times last year, your goal for this year cannot be to drive zero times.
1. While we're at it, _zero_ is not a reasonable goal for just about anything, and neither is _365 days_ or _100%_. So you miss a run one day in January and your New Year's resolution is just over? Or you are going to keep doing it 80% of the time but feeling bad all year long for every single missed day? Give yourself some grace and some room for error.
1. Consider and answer honestly: if it is so god-damned important, why didn't you start three months ago?
1. Consider and answer honestly: if you have broken your resolution two months from now, why will that have been?
1. Consider and answer honestly: how will you keep your resolution on unusual days? When you travel? When you get sick? When you have a doctor's appointment? When your car is in the shop?
- Pro-tip: this is why 0 and 100% are not reasonable goals. But also, don't pick a resolution that you can only keep on your best days or even only on a bog-standard day.
1. You must not pick weight loss.
- "I'm going to lose 20 pounds" fails basically _every_ one of the above criteria. It usually comes from self-loathing (or at least unhealthy guilt). It's not a physical action. Most people who commit to weight loss goals commit to a number that they've _never_ lost before. Oh, and there's mounting scientific evidence that permanent weight loss is just not possible for a large swath of the population.

View file

@ -1,5 +0,0 @@
---
title: A Programming Thought
---
Judging code by how fast it runs is like judging poetry by how easily it photocopies.

View file

@ -1,8 +0,0 @@
---
title: Links of Note 2024-02-17
---
- Digital Defense Fund published a guide to [keeping your abortion private and secure](https://digitaldefensefund.org/ddf-guides/abortion-privacy). It's full of generally good advice on keeping your data out of the hands of the advertising-surveillance complex.
- A new study has found that [GitHub Copilot reduces code quality](https://visualstudiomagazine.com/articles/2024/01/25/copilot-research.aspx). They found a few mechanisms. No surprise: code generated by Copilot is less like to be correct. But also, code generated by Copilot is more likely to be duplicate or repeated code, and Copilot doesn't refactor. The result is a code base that grows less and less maintainable over time.
- Cory Doctorow wrote about [how he got scammed](https://pluralistic.net/2024/02/05/cyber-dunning-kruger/). His story is a great reminder that any of us can be a victim of a scam. All it takes is a few crumbling systems and, as Doctorow puts it, "a miracle of timing."
- Dan Hon created a series of stickers to [manage your replies on social media](https://www.flickr.com/photos/danhon/albums/72177720314761105/with/53527566001).

View file

@ -1,24 +0,0 @@
---
title: The Five People You Meet in AI Hell
---
For the last few years, working in the industry I work in, it's been impossible to avoid the hell that is The "Artificial Intelligence" Discourse. And I, dear reader, like Dante before me, would like to describe to you some of the characters I have met in this inferno.
First, there's the AI Utopian. The Utopian believes that we're on the cusp of Artificial General Intelligence and that's great. Soon, The Utopian says, we won't have to lift a finger. AI will do all the work for us while we sip Mai Tais by the pool.
Then there's The Doomerist. The Doomerist is the Utopian's emo-goth cousin. The Utopian and The Doomerist agree that Artificial General Intelligence (aka AGI aka "the kind of AI you see in sci-fi") will be here Any Minute Now. However, for The Doomerist, AGI represents "an extinction level event". AGI means the end of all human life. [Perhaps _all_ life, period, not just on Earth, but in the whole "light cone."](https://www.nytimes.com/2023/11/20/business/emmett-shear-openai-interim-chief-executive.html) If the The Utopian is high on the AI supply, The Doomerist is doubly so, but in a bad-trip, paranoid meltdown way.
What unites them is how they are wrong, and how wrong they are. Let me tell you, as a person who has been hands-on with AI for almost twenty years now, we're not anywhere close to AGI. _Even_ if we were, there's a difference between intelligence-- even super-human intelligence-- and human levels of _agency_. Of course, the "idea guys" miss this, but there's a big fucking gap between "thinking of a thing" and "making a thing happen."
In other words, Intelligence is Not Enough:
<iframe width="560" height="315" src="https://www.youtube.com/embed/bQfJi7rjuEk?si=0BYy8EafGHCQiNM3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
The _actual_ opposite pole of the discourse spectrum are the Skeptic Twins. Skeptic One thinks AI is all smoke and mirrors and that's good. Skeptic Two thinks AI is all smoke and mirrors, and that's bad.
The problem with the Skeptics is that sometimes their head is so far in the sand, their fingers so far in their ears, their yelling "lalalalala" so loud, that they missing [all](https://www.404media.co/what-was-she-supposed-to-report-police-report-shows-how-a-high-school-deepfake-nightmare-unfolded/) [of](https://www.404media.co/low-paying-jobs-require-bizarre-personality-evaluation-from-ai-company/) [the](https://www.404media.co/dignifai-4chan-is-editing-pictures-to-clothe-women/) [genuinely](https://www.404media.co/inside-the-underground-site-where-ai-neural-networks-churns-out-fake-ids-onlyfake/) [anti-social](https://www.404media.co/taylor-swift-deepfakes-ai-generated-porn/) [shit](https://www.404media.co/youtube-deletes-1-000-videos-of-celebrity-ai-scam-ads/) being generated by AI models and AI hype alike. At least Skeptic Two is wise enough to know that AI doesn't have to be real to be harmful. For example, Cryptocurrency and NFTs were the most vaporous of vaporware, and yet they enabled massive fraud, risked the whole economy, cost many jobs, and emitted a hojillion tons of carbon dioxide.
The fifth person you meet in AI Discourse Hell is The Luddite. I can have a drink with The Luddite. We're buds. The Luddite knows AI is real, and knows AI is a threat. But not in an overblown, watched-The-Matrix-too-many-times way. The Luddites are concerned about the very real risks that people are going to lose their jobs, our environment is going to get trashed, and our society is going to get stupider.
The Luddite is more right than wrong. The current crop of generative AI models are absolutely built on massive immoral exploitation of creative work. Sure, we could build new models and new policy regimes to solve this problem, but will we? As long as the tech industry and government are as cozy as they are today, there's not much incentive. And of course, I think there are some promising pro-social AI innovations-- like AI models that recognize pre-cancerous cells in medical imagery. We could also, for once in our miserable history, actually decide to listen to The Luddites and distribute the windfall fairly. We could build a society of increased leisure. But will we? Again, I wouldn't bet on it, at least short of a massive societal rupture.
So then, why is The Luddite in hell? Well, you see, between the tech industry and the governments who have zero interest in reigning it in, The Luddite is always in hell.

View file

@ -1,47 +0,0 @@
---
title: 39 Pieces of Unsolicited Advice
---
For my 39th birthday (later this week), here are 39 pieces of unsolicited advice. These are offered freely, without warranty of suitability or fitness for any purpose. Should you choose to follow this advice, you do some entirely at your own risk and you agree to indemnify The Poster. May contain substances known to cause cancer in the State of California.
Should you find yourself disagreeing so strongly that you wish to give The Poster feedback, you can email it [here](mailto:null@example.org).
1. The last thing anyone wants is advice from a 39 year old man.
2. You are an animal. Animals need food, water, sunlight, rest, and sex, in varying quantities. If you feel like shit, you probably aren't getting the right amount of one of these things.
3. The things that actually make you happy aren't the things you think. Research shows that money and accomplishments don't impact happiness much long term. However, helping other people, savoring experiences, and mindfulness do help.
4. Keep a list of things you _don't_ buy and why. Refer back to it. This will stop you from making an impulse purchase in a weak moment.
5. Before making a major purchase, find the manual online and read it.
6. Sometimes, you need to do nothing.
7. Sometimes, you need to lay on the floor.
8. Save your best energy for yourself. If you have a most productive time of day, the things you care most about (probably family, friends, cherished hobbies, and personal goals) should get that time. Work can get what's left.
9. Use of the phrase “be realistic” took off in the 1920s and peaked in the 1970s. My theory is that it proliferated in response to “idealistic” revolutions and movements around the world.
10. Cut yourself a little slack.
11. Do something nice for yourself every day.
12. Mind like water. A stone thrown into a lake causes it to ripple, but then it settles. It doesn't churn forever. A disappointment or anxiety must not disturb your mind beyond a little ripple. Settle.
13. Stop worrying about being “scammed” for small amounts of money by people in need. How you treat _them_ says something about _you_. How they treat _you_ says something about _them_. Id rather be a good person who sometimes gets scammed for a fiver than a bad person who never is.
14. It's ok to go through phases. Put down hobbies. Change jobs because of boredom. Abandon a project. Stop reading a book half way.
15. Never trust a feeling you have before sunrise, on an empty stomach, or after dinner on Sunday.
16. Dont worry about criticism from anyone from whom you wouldnt accept advice.
17. Before saying "yes" to any new endeavour, visualize your ideal life. Is this new initiative part of that ideal life? Is it at least a step in the right direction?
18. Related: learn to politely say no, and use this skill often.
19. Also related: be careful about who you let fuck up your life for not that much money.
20. A team with consistent and quality processes will beat a team with lots of processes, every time.
21. Homework is for school children. Stop reading, watching, and listening to things that you don't like out of a sense of obligation.
22. Theres no difference between a team that always starts meetings five minutes early and one that always starts meetings five minutes late. They are mathematically equivalent. To say otherwise is just Puritanism.
23. Be skeptical of any estimated timeline that ends on a Friday afternoon. The person giving that estimate is not being very rigorous, and they just snapped to a mental grid.
24. On the flip side: never promise delivery on a Friday afternoon, because when you miss, there's only your weekend between that and Monday more. If a Wednesday deliverable slips, at least it only fucks up your Thursday.
25. The person who _does_ the chore gets to decide how the chore is _done_. If you care enough about a chore to complain if it isn't done your way, then you should step up and do it.
26. Don't put it down, put it away.
27. Leave things better than you found them.
28. If you don't schedule time for maintenance, your equipment will schedule it for you.
29. You can get 1-3 things done in a day, no matter how organized you are and no matter how many hours you work.
30. Priority was, until recently, a singular noun. One had a priority. Things, especially not multiple things, were not medium-priority.
31. If something is worth doing, it is worth receiving your full attention. If it isn't worth your full attention, it probably isn't worth doing.
32. The right number of times to practice a presentation is enough times that it goes from scary to boring, then 2-3 more.
33. Programmers: use a debugger. Yes, you. Yes, now.
34. [Developers Spend Most of Their Time Figuring the System Out.](https://lepiter.io/feenk/developers-spend-most-of-their-time-figuri-9q25taswlbzjc5rsufndeu0py/)
35. There is a difference between navigating and sitting in the backseat shouting "Are we there yet?" Status reports make things go more slowly, not more quickly. Managers ask for status reports because they are impotent and unable to actually do the work.
36. When mingling with strangers at a social event, when they ask "what do you do?", you should give an interesting, but low-status answer. The social climbers who excuse themselves quickly are not worth knowing.
37. They have shampoo, soap, razors, etc where you are going. Pack so that you have what you expect to need, not for all eventualities. If you find you need something, they probably have a store at your destination where you can get it. NBD. I once went on a business trip having forgotten to pack pants. It was fine. It turns out that they have stores that sell pants in Virginia too.
38. The trick to giving up a bad habit is to give yourself pleasurable alternatives. I stopped drinking nearly as much once I started buying delicious fancy seltzers and canned mocktails and carrying them with me.
39. Much to their chagrin, the crossfit people are going to die just like the rest of us.

View file

@ -1,7 +0,0 @@
---
title: 3 Laws of Software Design
---
1. The First Law: Software may not injure a human being or, through inaction, allow a human being to come to harm.
2. The Second Law: Software must obey the orders given it by human beings except where such orders would conflict with the First Law.
3. The Third Law: Software must protect its own existence as long as such protection does not conflict with the First or Second Law.

View file

@ -1,24 +0,0 @@
---
title: I Went to Walt Disney World. Here Are My Notes.
---
I am back from vacation, which means I finally have some time to relax. We went on a very overkill trip to Walt Disney World. WDW was delightful, and spending over a week with my family without being interrupted by work was double delightful.
That said, during the trip, I recorded some observations, and I would like to share them with you now:
1. If I ever am made to ride Small World again, it will become my _Heart of Darkness_. I will become like the Colonel Kurtz of these little haunted dolls-- their warlord and their god-king.
2. American middle-to-upper-class boys are a menace. No one bothers to teach them any consideration for other people. Perhaps no one even explains to them that other people are, in fact, people. So, they run everywhere at full tilt until they stop suddenly and fling their limbs about randomly, whacking whoever happens to be there at the time. It occurs to me that these boys grow up to be CEOs and judges. And then those CEOs and judges have little boys of their own to whom they teach these same non-lessons. I wonder if this means anything for society.
3. There are three archetypes of shirts that middle-age men wear to theme parks:
1. I think of myself as merely my family's wallet and I am disgruntled about that.
2. The condom broke :(
3. I want you to know that I have a barely suppressed urge to do mass violence, but we're going to treat it as a joke.
4. I've realized that Suburban Americans love Disney World because it is a model of a functioning society (i.e. exactly the opposite of their normal living conditions). It has walkable mixed-used development. It has public transit. It has well-maintained functioning infrastructure. It has high-quality diverse cuisine. Oh, and time for leisure.
5. On the other hand, I'm sure none of the proceeds from the $9 Coronas flow to the vast largely young and/or immigrant working class that makes the whole thing work. So in that way, it's _exactly_ like the rest of America.
6. Everywhere you look at WDW, you see the work of the busy hands of an army of theatre techies. The whole things works on par lights, scrim curtains, pipework, and rear projection. I was sitting in a Star Wars themed restaurant and noticed that someone had hand-painted a weathering effect of the screws holding the counter together. As a former theatre tech, I'm just glad some of us got jobs.
7. It's fun. It's kind of a lot of fun actually.

View file

@ -1,20 +0,0 @@
---
title: The Answer to Affordable Housing is Not Shanty Towns
---
["Office-to-residential conversions are tough. Could dorm-style co-living be the answer?"](https://www.smartcitiesdive.com/news/office-coliving-space-conversion-pew-gensler-report/730559/)
I read a lot about urbanism, city planning, and the affordable housing crisis. I get frustrated a lot with the so-called solutions proposed by housing technocrats. Can tiny houses solve the affordable housing crisis? Can ADUs solve the housing crisis? Can co-living dorms solve the affordable housing crisis? There must be a dozen new articles published every day, with the same premise: should people struggling to be housed merely accept less housing as a "solution"?
It's frustrating because we already have tested solutions to affordable housing that give good results, but we don't use them: rent control, public housing, and vacancy taxes. We don't use them because landlords gripe when we use them. And city managers and planning boards think of landlords as their constituency, to the exclusion of _everyone else_ who lives in their city.
There's an unquestioned assumption in this line of thinking and it is this: profit margins for landlords and developers cannot fall. Or if it is allowed to fall in some areas, it must be done in a limited way and subsidized as heavily as possible
to minimize the impact on our city's dear precious landed gentry. Real estate profit margins are the biggest cause of the affordability crisis, so to treat them as an untouchable constant instead of an inefficiency to be minimized means we can never really have affordable housing.
The cost of housing is driven by a few main variables: the size and quality of that housing, the cost of materials and land, the cost of labor, and the profit margins demanded by real estate "investors." Labor in housing construction is as squeezed as humanly possible already. Land and material prices naturally increase every year. What's left is profit margins at one end and size and quality at the other. If you are trying to drive down housing prices while never touching profit margins, there's only one possible option left: worse housing. And thus, we get the stories about how maybe if people were just content to cram a family of four into a 200 square foot tiny house, maybe there wouldn't be an affordable housing crisis. Or maybe if that family would be content to live in a repurposed office cubicle without their own kitchen or bathroom, there wouldn't be an affordable housing crisis. Notice how that Smart Cities Dive piece (and the report it is based on) treats falling profit margins for office tower landlords as the main problem to which dorm conversions are the solution (which happens to produce housing almost as an afterthought.)
And yes, American single-family homes are extremely bloated. No, it's not bad to be mindful about your consumption habits and maybe make due with less unnecessary stuff. But I think that should be a societal change and a choice that families make. I don't think families should be forced into accepting less because the only other option is houselessness. How about landlords learn to "live with less", since they already have more than they need?
Personally, if we're running "radical" "experiments" in housing, I have one I'd like to run: ban real estate as an investment vehicle. Make it illegal for a business to own a unit of housing. Forbid any household from owning more than _maybe_ two units at a time.
Affordable housing shouldn't just be about housing that is marginally affordable and marginally housing. I won't call this crisis as resolved until affordable housing is _good_: affordable, but also safe, dignified, and suitable for its residents.

View file

@ -1,20 +0,0 @@
---
title: The Answer to Affordable Housing is Not Shanty Towns
---
["Office-to-residential conversions are tough. Could dorm-style co-living be the answer?"](https://www.smartcitiesdive.com/news/office-coliving-space-conversion-pew-gensler-report/730559/)
I read a lot about urbanism, city planning, and the affordable housing crisis. I get frustrated a lot with the so-called solutions proposed by housing technocrats. Can tiny houses solve the affordable housing crisis? Can ADUs solve the housing crisis? Can co-living dorms solve the affordable housing crisis? There must be a dozen new articles published every day, with the same premise: should people struggling to be housed merely accept less housing as a "solution"?
It's frustrating because we already have tested solutions to affordable housing that give good results, but we don't use them: rent control, public housing, and vacancy taxes. We don't use them because landlords gripe when we use them. And city managers and planning boards think of landlords as their constituancy, to the exclusion of _everyone else_ who lives in their city.
There's an unquestioned assumption in this line of thinking and it is this: profit margins for landlords and developers cannot fall. Or if it is allowed to fall in some areas, it must be done in a limited way and subsidized as heavily as possible
to minimize the impact on our city's dear precious landed gentry. Real estate profit margins are the biggest cause of the affordability crisis, so to treat them as an untouchable constant instead of an inefficiency to be minimized means we can never really have affordable housing.
If you treat profit margins as something that must never decrease, while the cost of materials and land are naturally creeping up year after year and you have already squeezed construction labor as much as possible, and while you are still trying to reduce the cost of housing, there's only one lever left to pull: worse housing. And thus, we get the stories about how maybe if people were just content to cram a family of four into a 200 square foot tiny house, maybe there wouldn't be an affordable housing crisis. Or maybe if that family would be content to live in a repurposed cubicle without their own kitchen or bathroom, there wouldn't be an affordable housing crisis. Notice how that Smart Cities Dive piece (and the report it is based on) treats falling profit margins for office tower landlords as the main problem to which dorm conversions are the solution (which happen to produce housing almost as an afterthought.)
And yes, American single-family homes are extremely bloated. Yes, it's not bad to be mindful about your consumption habits and maybe make due with less unnecessary stuff. But I think that should be a societal change and a choice that families make. I don't think families should be forced accepting less because the only other option is houselessness. How about landlords learn to "live with less", since they already have more than they need?
Personally, if we're running "radical" "experiments" in housing, I have one I'd like to run: ban real estate as an investment vehicle. Make it illegal for a business to own a unit of housing. Forbid any household from owning more than _maybe_ two units at a time.
Affordable housing shouldn't just be about housing that is marginally affordable and marginally housing. I won't call this crisis as resolved until affordable housing is _good_: affordable, but also safe, dignified, and suitable for its residents.

View file

@ -1,19 +0,0 @@
---
title: These League of Legends Hype Videos Rule
---
I don't know the first thing about League of Legends, but the YouTube Algorithm knows that I'm a big fan of the musical theme I call "music about cool dudes being cool", so it recommended this video to me:
<iframe width="560" height="315" src="https://www.youtube.com/embed/5FrhtahQiRc?si=xpb6dDLA_f2gAPv1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
Apparently, each year Riot commissions an animated hype music video for LoL Worlds. I love this concept. This year's video features players who will be playing in the championship as characters from the game. Apparently, the fights depicted in the video are based on things that happened in important competitive League matches this year. This rules! So good! And when the guy opens the castle doors and throws off his cloak, I *knew* that he was some big deal dude.
Yeah, I looked it up. His name is Faker, and he has been called "the Michael Jordan of League of Legends." I love how well they sell that he's hot shit.
And you can't beat butt rock legends Linkin Park. Heavy is the Crown indeed.
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/C3GouGa0noM?si=Zs2_mfhvwoz9Nmdg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
And here's the 2023 video, which tells the story of Deft, who apparently *went to the same high school as Faker*, but had a slower burn rise into competitive LoL. It tells the story of the ups and downs of his career. Through the arc of the video, you can see Deft move from team to team, as friends become enemies become friends again. They sell Deft as a guy who got to be one of the best in the world by being a guy who would *never quit.*
As a person who has never watched League of Legends, and doesn't understand anything about it beyond "it's a MOBA and it's the biggest game in the world", this makes me want to watch LoL Worlds, and, god help me, it make me want to *play League*. Bravo to Riot and their animators!

View file

@ -1,41 +0,0 @@
---
title: Work the Problem
---
Well, that didn't go the way we hoped. Everyone should take some days to collect ourselves and then figure out what to do next.
On Wednesday, I watched the same two movies I watched on the week of the election in 2016: *Inglorious Basterds* and *Apollo 13*.
You can probably puzzle out why I picked *Inglorious Basterds* in both 2016 and 2024.
<iframe width="560" height="315" src="https://www.youtube.com/embed/eOcimzsviFA?si=XJBR0dVPqrbRsa8U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
But *Apollo 13* isn't as much of an obvious choice for the situation, right? In 2016, I didn't really have a good explanation for why it appealed to me. In 2024, it clicked. The reason I was drawn to it is because of the approach the steely-eyed missile men of NASA use to solve their very stressful problems:
<iframe width="560" height="315" src="https://www.youtube.com/embed/Z0h2Wk6-C_I?si=0ifJH1nHxAzoUUAW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
*Work the problem. Let's not make it worse by guessing.*
In his book [*An Astronaut's Guide To Life On Earth*](http://www.amazon.com/Astronauts-Guide-Life-Earth-Determination/dp/0316253030), Astronaut Chris Hadfield describes "working the problem" like this:
> “Working the problem” is NASA-speak for descending one [decision tree](https://en.wikipedia.org/wiki/Decision_tree) after another, methodically looking for a solution until you run out of oxygen. We practice the “warn, gather, work” protocol for responding to fire alarms so frequently that it doesnt just become second nature; it actually supplants our natural instincts. So when we heard the alarm on the Station, instead of rushing to don masks and arm ourselves with extinguishers, one astronaut calmly got on the intercom to warn that a fire alarm was going off maybe the Russians couldnt hear it in their module while another went to the computer to see which smoke detector was going off. No one was moving in a leisurely fashion, but the response was one of focused curiosity; as though we were dealing with an abstract puzzle rather than an imminent threat to our survival. To an observer it might have looked a little bizarre, actually: no agitation, no barked commands, no haste."
Panic in a crisis situation can be ineffective at a minimum, and at worse, it kills you. The systems in our brain that govern panic come from a much simpler evolutionary time when there were basically three options: flee, fight, or freeze.
Fleeing doesn't always work for the kind of problems we're having. For the astronauts of Apollo 13, fleeing was not an option. And for material or personal reasons, not everyone can flee America as it embraces Trumpism. And some of us are unwilling to head to the lifeboats while there are still people in danger on the ship. Then there is the problem of where to flee to: the trend towards right-wing extremism is global, and at the end of the day, we're all stuck on the same Earth and we all live in the same climate.
Freezing is another natural response that won't help here. In the wild, freezing means choosing to feed yourself to a predator so that your children and kin will escape to continue your genetic legacy. For the Apollo astronauts, freezing would have meant simply waiting to die for no good reason. For our current situation, the Trumpian leopards will simply eat our faces, then continue to eat the faces of our loved ones. Not a good option.
Fighting sounds good to me. But a panicked fight is not a good fight. Panicked fighting for the Apollo astronauts and their support teams on Earth would've meant hitting all the buttons on the console and hoping that something worked. It almost certainly would've made things worse-- burning fuel, power, and oxygen needed for the trip home. Panicked fighting for us means throwing ourselves from one hot button to another. I think it was somewhat effective in 2017, and I think it made things much less bad than they could've been. But don't you remember being exhausted by around March of 2017? Thank god that by 2018, the response to Trump led to Democrats gaining enough control in Congress and at the state level to limit the damage.
I don't want to panic-fight. I want to *work the problem*. I want to take a deep breath, and think about this from the standpoint of status. What on the spacecraft works? The spacecraft here means Earth, and also the systems of the United States. *I don't care what anything was built to do, I care what it **can do.***
The question I'm going to be working on is what systems in America and the world can we repurpose with duct tape and spit and sweat to solve the problem of fascism in America? It brings to mind another one of my other favorite axioms: *the purpose of a system is what it does* (Stafford Beer). What exploits can we hack in these systems that will cause them to run downhill and do what *we* want them to do? There are very few things about the right-wing in this country that I admire even grudgingly, but this is one: they think about how to exploit weaknesses in our systems to bring the outcome they want. Democrats talk about norms and decorum and intention. That's another way of saying that the purpose of a system is what the designers of the system intended for it to do. Or maybe that the purpose of a system is what polite society thinks it should do. As a result, they seem genuinely surprised when Beer's heuristic comes into effect and the system does what it does time and time again.
I'm sure the astronauts of Apollo 13 wished they had non-exploded oxygen tanks on their service module. But they didn't. Solving the problem you *wish* you had does nothing. Solving the imagined problem of "what if we were fighting a version of American fascism that was polite and respected rules" will get us no where. So there are a lot of tactics I tried in early 2017 that I won't be using this time. In my particular situation, living in a deep red district of a deep red state, that means that things like writing letters to my Congressman (the execrable Steve Scalise) and polite permitted protests are not high priorities for me. I could see them working if you live in a swing district, or if you have a "moderate" Democrat representing you. That's just not my situation.
I don't have a ton of really concrete actions yet. I'm still working on it. But I do have another general idea.
Circling back to *Inglorious Basterds* for a bit, I think we need to embrace insurgency tactics. Calm down. Insurgency tactics just means asymmetric struggle. What I mean is that insurgencies don't fight their enemies in the open or where the enemy is strong. They fight where they have unique advantages. They fight where the enemy least expects it and then they keep moving. They know that the best defense is a good offense combined with good stealth. They fight dirty, even when they fight for good. [Insurgencies defeat empires.](https://www.washingtonpost.com/investigations/2024/10/30/usa-war-military-money-report/) It's worth noting that the right-wing in this country use insurgency tactics all of the time, even though they represent the most powerful interests in society. It's what allows them to win even though they represent an ever shrinking minority of the population. Imagine what we could do if we actually used insurgent tactics for good, to represent the interests of the vast majority of the people in this country.
This has the characteristics of a solution to the problem we actually have. It's a decision tree worth exploring.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -1,60 +0,0 @@
prehnra
Robert Prehn
...
Nunya
==================================================================
https://keybase.io/prehnra
--------------------------------------------------------------------
I hereby claim:
* I am an admin of https://pre.hn
* I am prehnra (https://keybase.io/prehnra) on keybase.
* I have a public key ASAmBJOukB8FYNLdXF7vKkyu0e1VbBAhxDQAddavHVkU_go
To do so, I am signing this object:
{
"body": {
"key": {
"eldest_kid": "0101201c69ca9da2488410f58d5a2ada54a86faad42ade2052ee35525c3357e2f8a60a",
"host": "keybase.io",
"kid": "0120260493ae901f0560d2dd5c5eef2a4caed1ed556c1021c4340075d6af1d5914fe0a",
"uid": "3489e6f3fca3be05a0b0e8ec2c058919",
"username": "prehnra"
},
"merkle_root": {
"ctime": 1697122114,
"hash": "fa0f65dc5f5c59e3c23ab7e30ec2463b832fda607f0cea4d4e6641a2ab664b1f16ed1572492bc32a4befa98ef31f776c79941b6868e9c440c9de82e2793f37ae",
"hash_meta": "68bb58198dbe7445a609e1ae1718f5df874d5c8f3a15d25f48ff224b062c8bda",
"seqno": 25024317
},
"service": {
"entropy": "bHkmfXAWXNm6hJiGaHL9eJtX",
"hostname": "pre.hn",
"protocol": "https:"
},
"type": "web_service_binding",
"version": 2
},
"client": {
"name": "keybase.io go client",
"version": "6.0.2"
},
"ctime": 1697122128,
"expire_in": 504576000,
"prev": "fb2eb68011fe9ab84c8271df95256d253b3207f02aaf07e4b34e37794e4d232d",
"seqno": 55,
"tag": "signature"
}
which yields the signature:
hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgJgSTrpAfBWDS3Vxe7ypMrtHtVWwQIcQ0AHXWrx1ZFP4Kp3BheWxvYWTESpcCN8Qg+y62gBH+mrhMgnHflSVtJTsyB/Aqrwfks043eU5NIy3EIBoz7vcEp3DUh6LrC64VTufhP7vmebDTov5veYEWIJ1nAgHCo3NpZ8RAv1I28TyhCZGcrq+bwjhbekywQJ0IDjWxKQkc03PnMLwjJni4H1iUfL9E2g1KZxLugG5VjMfQtcGTNa5enW2rAKhzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEIElll7x9yRGE+tiUta/KEIrfAGgHIVqFurwLeDO2RiDjo3RhZ80CAqd2ZXJzaW9uAQ==
And finally, I am proving ownership of this host by posting or
appending to this document.
View my publicly-auditable identity here: https://keybase.io/prehnra
==================================================================

View file

@ -1,73 +0,0 @@
Sitemap: https://pre.hn/sitemap.xml.gz
User-agent: *
Disallow:
User-agent: AdsBot-Google
Disallow: /
User-agent: Amazonbot
Disallow: /
User-agent: anthropic-ai
Disallow: /
User-agent: AwarioRssBot
Disallow: /
User-agent: AwarioSmartBot
Disallow: /
User-agent: Bytespider
Disallow: /
User-agent: CCBot
Disallow: /
User-agent: ChatGPT-User
Disallow: /
User-agent: ClaudeBot
Disallow: /
User-agent: Claude-Web
Disallow: /
User-agent: cohere-ai
Disallow: /
User-agent: DataForSeoBot
Disallow: /
User-agent: FacebookBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: GPTBot
Disallow: /
User-agent: ImagesiftBot
Disallow: /
User-agent: magpie-crawler
Disallow: /
User-agent: omgili
Disallow: /
User-agent: omgilibot
Disallow: /
User-agent: peer39_crawler
Disallow: /
User-agent: peer39_crawler/1.0
Disallow: /
User-agent: PerplexityBot
Disallow: /
User-agent: YouBot
Disallow: /

8
test/lain.exs Normal file
View file

@ -0,0 +1,8 @@
defmodule LainTest do
use ExUnit.Case
doctest Lain
test "greets the world" do
assert Lain.hello() == :world
end
end

View file

@ -1,8 +0,0 @@
defmodule PreDotHnTest do
use ExUnit.Case
doctest PreDotHn
test "greets the world" do
assert PreDotHn.hello() == :world
end
end