aboutsummaryrefslogtreecommitdiff
path: root/_posts
diff options
context:
space:
mode:
Diffstat (limited to '_posts')
-rw-r--r--_posts/2022-09-21-ogham-balanced-elevenary.md22
-rw-r--r--_posts/2022-10-30-taxonomy-of-open-source.md25
-rw-r--r--_posts/2023-02-12-uuid-versions.md170
-rw-r--r--_posts/2023-05-23-two-heresies-about-link-rot.md42
-rw-r--r--_posts/2023-06-15-the-derivative-gardens-license.md18
-rw-r--r--_posts/2023-08-17-25-hour-time.md54
-rw-r--r--_posts/2023-11-26-tiny-cactus-cloudtest02.md29
-rw-r--r--_posts/2023-12-27-no-mans-sky-unless.md20
-rw-r--r--_posts/2023-12-31-the-browser-is-a-terrible-place-for-art.md24
-rw-r--r--_posts/2024-09-08-abdication-is-not-simplicity.md25
-rw-r--r--_posts/2024-09-20-eggbug-forever-ffxiv.md28
-rw-r--r--_posts/_posts.11tydata.js1
12 files changed, 458 insertions, 0 deletions
diff --git a/_posts/2022-09-21-ogham-balanced-elevenary.md b/_posts/2022-09-21-ogham-balanced-elevenary.md
new file mode 100644
index 0000000..f6c4367
--- /dev/null
+++ b/_posts/2022-09-21-ogham-balanced-elevenary.md
@@ -0,0 +1,22 @@
+---
+title: writing balanced elevenary in the ogham script
+---
+
+**for no particular reason**
+
+digits, from negative five to positive five:
+
+<span style="font-size:200%">ᚅ ᚄ ᚃ ᚂ ᚁ ᚋ ᚆ ᚇ ᚈ ᚉ ᚊ</span>
+
+(romanized as N S F L B M H D T C Q)
+
+radix point <span style="font-size:200%">ᚖ</span> (left as . when romanizing)
+
+a few nice values: <span style="font-size:200%">ᚆᚅᚈᚖᚆᚊᚇᚋᚅ</span>, <span style="font-size:200%">ᚈᚊᚇ</span>, <span style="font-size:200%">ᚈᚖᚇᚅᚆᚊᚆ</span>
+
+fuck around with it y'self:
+
+<div class="cohost-style-embed">
+<div style="left: 0; width: 100%; height: 300px; position: relative;"><iframe src="https://codepen.io/boringcactus/embed/preview/abGwgoG?default-tabs=js%2Cresult&height=300&host=https%3A%2F%2Fcodepen.io&slug-hash=abGwgoG" style="top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0;" allowfullscreen></iframe></div>
+<div class="cohost-style-embed-link"><a href="https://codepen.io/boringcactus/pen/abGwgoG">https://codepen.io/boringcactus/pen/abGwgoG</a></div>
+</div>
diff --git a/_posts/2022-10-30-taxonomy-of-open-source.md b/_posts/2022-10-30-taxonomy-of-open-source.md
new file mode 100644
index 0000000..cfe2a4e
--- /dev/null
+++ b/_posts/2022-10-30-taxonomy-of-open-source.md
@@ -0,0 +1,25 @@
+---
+title: some axes for a taxonomy of open source
+description: a list
+---
+
+- maintenance effort and expectations: professionally maintained / casually maintained / not maintained
+- source of priorities: owner-driven / community-driven
+- desire for input: PRs welcome / issues welcome / view-only
+- license standards: bare minimum / give code back / don't be evil / be specifically good
+- how bills get paid: not users' problem / crowdfunding / selling support / we productized the hosting so if you also productize the hosting you're being a dick
+
+<details>
+<summary>for example</summary>
+
+- React is professionally maintained, owner-driven, PRs welcome, bare minimum, not users' problem
+- MongoDB is the same but give code back and we productized the hosting
+- SQLite is professionally maintained, owner-driven, issues welcome, bare minimum, selling support
+- anything that runs on github sponsors or patreon is crowdfunding
+- the Hippocratic License or some of the others are don't be evil
+- ACSL counts as be specifically good
+- anti-licenses are the secret fifth tier of license standards, Good Fucking Luck
+- some projects are actually community-driven but I can't think of one off the top of my head
+- most of my side projects are not maintained, owner-driven, view-only, Good Fucking Luck, and crowdfunding at the time they were written but currently not your problem.
+
+</details>
diff --git a/_posts/2023-02-12-uuid-versions.md b/_posts/2023-02-12-uuid-versions.md
new file mode 100644
index 0000000..3f9c257
--- /dev/null
+++ b/_posts/2023-02-12-uuid-versions.md
@@ -0,0 +1,170 @@
+---
+title: UUID versions through the ages
+---
+
+UUIDs are neat. y'know, `cfbff0d1-9375-5685-968c-48ce8b15ae17` type of shit. if you're like me until a few days ago, all you know about the types of UUID is that v4 is the good one. but why are there other ones? is there a secret better one? why are the dashes asymmetrical? let's take a (roughly paraphrased from [wikipedia](https://en.wikipedia.org/w/index.php?title=Universally_unique_identifier&oldid=1136241716) and probably not quite accurate) look.
+
+## wait why even
+
+sometimes you need an ID for something you are putting in the computer, so that you have a stable way to refer to it even if all the editable fields on it change. the simplest possible approach is to give the first thing ID 1, the second thing ID 2, and so on. cohost works this way right now - as i'm editing it, this draft post has ID 1009270, meaning this is the just-over-a-millionth thing in the posts table.
+
+your database sits there going "the next post has ID 8. oh, new post? it has ID 8, okay the next post has ID 9." and all is well. except a year later you have a million posts and a bunch of people posting all at once, and every new post needs a new ID but they have to get created one at a time in the database so that they all get the right ID. If You're In Line (To Get The Next Post ID), Stay In Line. and the only way to know what the next post ID is is to check with the database, so you can't do things like save drafts offline with proper IDs. (staff probably doesn't want that anyway, but we need something vaguely similar at work, which is how i got here.) if you need to work at, say, Twitter's scale, or you need to be able to generate IDs without checking with the database, you need something more involved than just sequential IDs.
+
+## wait why even
+
+sometimes you need an ID for something you are putting in the computer, so that you have a stable way to refer to it even if all the editable fields on it change. the simplest possible approach is to give the first thing ID 1, the second thing ID 2, and so on. cohost works this way right now - as i'm editing it, this draft post has ID 1009270, meaning this is the just-over-a-millionth thing in the posts table.
+
+your database sits there going "the next post has ID 8. oh, new post? it has ID 8, okay the next post has ID 9." and all is well. except a year later you have a million posts and a bunch of people posting all at once, and every new post needs a new ID but they have to get created one at a time in the database so that they all get the right ID. If You're In Line (To Get The Next Post ID), Stay In Line. and the only way to know what the next post ID is is to check with the database, so you can't do things like save drafts offline with proper IDs. (staff probably doesn't want that anyway, but we need something vaguely similar at work, which is how i got here.) if you need to work at, say, Twitter's scale, or you need to be able to generate IDs without checking with the database, you need something more involved than just sequential IDs.
+
+## version 1
+
+in the early 90s, some UNIX people ran into this problem when drawing up their Distributed Computing Environment. they called [their solution](https://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm) "Universal Unique Identifiers", which they call "an identifier that is unique across both space and time". it's written as a hexadecimal string, but it can be stored as just the 16 bytes that are represented by that hexadecimal string. the way they make sure it's unique across both space and time is actually pretty straightforward: part of the UUID encodes the space where it was generated, and part of the UUID encodes the time where it was generated.
+
+the UUID format has two control fields and three data fields. the version field is pretty straightforward - it's 1 for UUIDv1, 2 for UUIDv2, etc. at this point, they only had 1 and 2, but they left room in the spec for up to 15 just in case. there's also a variant field, which says whether it's a normal UUID (`10`, hex value `8` through `b`) or some other bullshit that may or may not adhere to any of the rest of this spec.
+
+<details>
+
+<summary>other bullshit</summary>
+
+if the variant field is `0` then it's a UUID from Apollo Computer's Network Computing System, which had UUIDs before DCE but defined them in a slightly different way. if it's `110` then it's a UUID but the wrong endian, which Microsoft does sometimes when it makes UUIDs (it calls them GUIDs, because they're thinking too small, merely Global rather than Universal). if it's `111` then you're living in the future where they assigned a meaning to variant `111`. what's it like? how's the whole climate change thing going?
+
+</details>
+
+the data fields are
+
+- timestamp, which is measured since the start of the Gregorian calendar with 100ns resolution (which, with 60 bits available, repeats every 3653 years). this is how they make sure the UUID is unique across time.
+
+- clock sequence, which starts at a random number and goes up by one if time goes backwards, to ensure that things like clock drift or leap seconds don't lead to collisions. this is how they make sure the UUID is *actually* unique across time.
+
+- node, which is just the MAC address on your network card (or one of them, if you've got more than one), since different network cards already have to have different MAC addresses in order for networking to happen. this is how they make sure the UUID is unique across space.
+
+this is how we get that weird hyphen asymmetry, the groups come directly from the UUID data fields:
+
+<div style="display: grid; grid-template-rows: 1fr 1fr;"><div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 5; border-bottom: 1px solid;">version</span><span style="grid-column: 8; border-bottom: 1px solid;">variant</span></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><kbd style="font-weight: 600;">1a8188ce</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">aa78</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">1</kbd><kbd style="font-weight: 600;">1ed</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">a</kbd><kbd style="font-weight: 600;">fa1</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">0242ac120002</kbd></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 1; border-top: 1px solid;">time_low</span><span style="grid-column: 3; border-top: 1px solid;">time_mid</span><span style="grid-column: 6; border-top: 1px solid;">time_hi</span><span style="grid-column: 8 / 10; border-top: 1px solid;">clock sequence</span><span style="grid-column: 11; border-top: 1px solid;">node</span></div></div>
+
+you may have noticed that the time is split into three pieces, for the low 32 bits, the middle 16 bits, and the high 12 bits. why split it up like that? well, i don't know, but i suspect it makes a lot of things easier to split the 60 bit timestamp into at least 32 and 28 (and maybe splitting the 28 into 16 and 12 makes something easier in a way i'm not seeing?). for one, 64-bit CPUs weren't mainstream yet, and for two, they had creative alternate uses for that time_low field.
+
+## version 2
+
+like a lot of multi-user operating systems, UNIX has users and groups, and allows for permissions management based on those users and groups. users and groups both have textual names and numeric IDs, so if you want to stably refer to a specific user or group, you can use its user ID or group ID. however, different computers can have different sets of users and groups, so if you're making the Distributed Computing Environment, you need a way to refer to a specific user or group on a specific machine. you're building on top of UNIX, because you're the Open Software Foundation (later The Open Group), so you have user and group IDs locally already. and you already made this UUID format, which has fields that refer to a specific machine. the other fields are already taken for time and also-time, but you didn't promise they'd *always* be time, right?
+
+in UUIDv2 (which the [DCE spec](https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) calls the "security version"), the time_low field is literally just a UNIX user/group ID. the low byte of the clock sequence field is repurposed to specify whether it's a user or a group (or a secret third thing, an organization).
+
+i have several questions. for one, what about the other time fields? time_mid ticks up once every 7 minutes, if you construct your UUIDv2 out of a UUIDv1. do you just leave it at zero and let time_hi tick up every 325 days? do you leave mid and hi both at zero and party like it's 1582? for two, had they not invented MAC address spoofing yet? these days you can usually change your network card's MAC address to something else, so using that for anything security-related strikes me as highly dubious. for three,, what? just in general? why would you do this? this is some 5 Minute Crafts tier lifehackery. please refrain.
+
+presumably this worked well enough for DCE, but it has not withstood the test of time. i don't know that UUIDv2 even counts as a UUID, but it follows the UUID format and put a 2 in the version number slot, and so it lives on solely as negative space in the UUID version number range. (this is also apparently the deal with IPv5.)
+
+UUIDv2 may or may not have been a good idea, but the concept of "what if you had a UUID based on some specific value other than the current time" had legs.
+
+## version 3
+
+DCE was done being written, and then it kinda died, but people kept using UUIDs. DCE was a legacy-style Proper Goddamn Specification, written by the consortium that had since become The Open Group, who also run POSIX and the Single UNIX Specification and all that jazz (?? when the posix is sus !), but that sort of doorstopper spec was overkill for the humble UUID. what it needed, as a piece of computer bullshit, was an RFC. and so in 2005 the UUID was defined again in [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122), which kept v1, reduced v2 to one sentence, and added some new versions.
+
+one way to think of the goal of UUIDv2 is that it's about referring to an object that already has a contextually unique ID. in v2, that object is either a user or a group, and that context is a machine. v3 is a little more flexible, but one of the contexts mentioned in the RFC is domain names, so let's look at that.
+
+say i want something in the format of a UUID that refers to the domain name `example.com`. one option would be to take the MD5 hash of `"example.com"`, look at the first 16 bytes, line that up with the UUID format definition, and set the version and variant to the right values. this is cool, and it basically already works for domain names, but we want flexibility. if you and i both want to do the UUIDv2 thing of referring to users on a machine, and my context is my machine and your context is your machine, and both of us have a user named `cactus`, oops, we have the same UUID, that's hardly Universally Unique. we need to include the context in what we're MD5ing, and we need to guarantee that different contexts have different values. and there's nothing computer people love more than recursion, so let's give the context a damn UUID.
+
+to make a UUIDv3, you need a name (which is just some text) and a UUID for your "name space" (which is the context in which your name is unique). take the binary representation of the namespace UUID, append the name, MD5 it, copy that into your UUID structure, set the version and variant, and you are done.
+
+the RFC defines some name space UUIDs already, like `6ba7b810-9dad-11d1-80b4-00c04fd430c8` for domain names, so we can check this ourself:
+
+```python
+>>> import hashlib
+>>> import uuid
+>>> dns_namespace = uuid.UUID("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
+>>> hashlib.md5(dns_namespace.bytes + b"example.com").hexdigest()
+'9073926b929fd1c26bc9fad77ae3e8eb'
+>>> uuid.uuid3(dns_namespace, "example.com")
+UUID('9073926b-929f-31c2-abc9-fad77ae3e8eb')
+```
+
+this is pretty damn neat. if you have something that's contextually unique and you want to turn it into something that's globally unique, this is a really cool way to do that. (spoilers, except for one thing, which you may have noticed if you know your hash functions.) but this is only sometimes a problem you have; other times, you don't have anything unique yet, and you want something ex nihilo. v1 is still good, if you've got a timestamp and a MAC address, but what if you're doing something like JS development where you can't exactly check the MAC address you're running on? well, satan help you. or what if that 100ns resolution isn't good enough like it was in the 90s?
+
+## version 4
+
+set the version and variant. fill the rest with random bits. there is no step 3.
+
+if you had asked me to guess last week what a UUIDv4 was, i'd have just guessed it was 128 random bits (if you made me count how long it was). and i'd have been wrong, but only by six bits. which is neat, but also a little bit bullshit, because like. me from last week wants those bits back!
+
+those six bits are for compatibility with the rest of the UUID universe, but if you're just looking for some random bytes to throw in your id column, you don't need compatibility with UUIDv1, you could just make some random bytes! and 16 of them is probably overkill for your use case anyway!
+
+wait hang on a minute, did that say MD5 earlier?
+
+## version 5
+
+turns out MD5 sucks. you know what's really cool? SHA-1.
+
+UUIDv5 is just UUIDv3 again, but with SHA-1 instead of MD5.
+
+```python
+>>> hashlib.sha1(dns_namespace.bytes + b"example.com").hexdigest()
+'cfbff0d193753685568c48ce8b15ae17d93cc34c'
+>>> uuid.uuid5(dns_namespace, "example.com")
+UUID('cfbff0d1-9375-5685-968c-48ce8b15ae17')
+```
+
+thankfully, SHA-1 is the last word in hashing algorithms, it's never had problems and it's known to be very good. now to take a big sip of my coffee and check the NIST website.
+
+<div class="cohost-style-embed">
+{% renderTemplate "webc" %}
+<opengraph-embed
+ href="https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm"
+ site-href="https://www.nist.gov"
+ site-favicon="https://www.nist.gov/themes/custom/nist_www/favicon.ico"
+ img-src="https://www.nist.gov/sites/default/files/images/2022/12/14/SecureHashAltogirthm23_Released_960x600_v4_A.png"
+ datetime="2022-12-15T12:00:00.000Z"
+>
+<span slot="title">NIST Retires SHA-1 Cryptographic Algorithm</span>
+The venerable cryptographic hash function has vulnerabilities that make its further use inadvisable.
+<span slot="site-name">NIST</span>
+<span slot="site-domain">nist.gov</span>
+<span slot="date">Dec&nbsp;15,&nbsp;2022</span>
+</opengraph-embed>
+{% endrenderTemplate %}
+<div class="cohost-style-embed-link"><a href="https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm">https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm</a></div>
+</div>
+
+oh. that seems bad. when is UUIDv6?
+
+## version 6
+
+well. there's a [draft RFC](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format) making updates to the UUID RFC, but it doesn't solve that problem, it solves different problems.
+
+one of the cool things about UUIDv1 is that you can decode the timestamp back out of it, and you don't need a separate field for the time when your object was created, because its ID tells you when it was created. however, the weird slicing and dicing that UUIDv1 does to the timestamp field means sorting by time is complicated, since the low 32 bits come first and the high 12 bits come last.
+
+UUIDv6 puts the whole timestamp in order, so that the most significant bit is first.
+
+<div style="display: grid; grid-template-rows: 1fr 1fr;"><div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 5; border-bottom: 1px solid;">version</span><span style="grid-column: 8; border-bottom: 1px solid;">variant</span></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><kbd style="font-weight: 600;">1edaa9b4</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">e919</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">6</kbd><kbd style="font-weight: 600;">172</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">a</kbd><kbd style="font-weight: 600;">0d0</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">6721ef312724</kbd></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 1; border-top: 1px solid;">time_high</span><span style="grid-column: 3; border-top: 1px solid;">time_mid</span><span style="grid-column: 6; border-top: 1px solid;">time_low</span><span style="grid-column: 8 / 10; border-top: 1px solid;">clock sequence</span><span style="grid-column: 11; border-top: 1px solid;">node</span></div></div>
+
+it keeps the clock sequence as-is from v1, but it explicitly recommends using random data instead of the MAC address for the node field, which is good.
+
+hang on, while we're messing with silly things from v1, what the hell is up with time since the gregorian calendar?
+
+## version 7
+
+what if we just did unix timestamp and randomness, so that we had easy sorting and decoding but also uniqueness, without any bullshit.
+
+well, v7 is that. 48 bits of unix timestamp in milliseconds (rolls over every 8920 years), 74 random bits, 6 control bits for version and variant.
+
+<div style="display: grid; grid-template-rows: 1fr 1fr;"><div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 3; border-bottom: 1px solid;">version</span><span style="grid-column: 6; border-bottom: 1px solid;">variant</span></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><kbd style="font-weight: 600;">0186443f-2c00</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">7</kbd><kbd style="font-weight: 600;">5fb</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">8</kbd><kbd style="font-weight: 600;">00a-7ec0f02a852d</kbd></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 1; border-top: 1px solid;">time</span><span style="grid-column: 4; border-top: 1px solid;">rand_a</span><span style="grid-column: 6 / 10; border-top: 1px solid;">rand_b</span></div></div>
+
+this is the real good one. the only reason not to use it is that the RFC isn't approved so it isn't quite official yet, but if you don't need to care, find an implementation in your language of choice and go to fuckin town.
+
+but what if yolo?
+
+## version 8
+
+if yolo, then you can use version 8. all of the version-specific fields are defined to be custom, so you can put whatever the hell nonsense you need to there.
+
+<div style="display: grid; grid-template-rows: 1fr 1fr;"><div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 3; border-bottom: 1px solid;">version</span><span style="grid-column: 6; border-bottom: 1px solid;">variant</span></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><kbd style="font-weight: 600;">b00b5101-6969</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">8</kbd><kbd style="font-weight: 600;">420</kbd><kbd style="font-weight: 600;">-</kbd><kbd style="font-weight: 600;">9</kbd><kbd style="font-weight: 600;">a55-676179736578</kbd></div> <div style="display: grid; grid-column: 1 / 99; grid-template-columns: subgrid; text-align: center;"><span style="grid-column: 1; border-top: 1px solid;">custom_a</span><span style="grid-column: 4; border-top: 1px solid;">custom_b</span><span style="grid-column: 6 / 10; border-top: 1px solid;">custom_c</span></div></div>
+
+## so what did we learn
+
+UUIDs are pretty neat. if you need a database identifier and you get to pick something from scratch, use v7, it gives you timestamps for free. if you have things that are contextually unique and you want to turn them into universally unique IDs with a standard format, v5 is for you. if all you need is some random shit, v4 is that in the UUID format, but if you don't need the UUID format, you can also just use random bytes directly. if what you need is very specific shit nobody's thought of before, but in the UUID format, that's v8. v6 is the worse version of v7, v3 is the worse version of v5, v1 is the worse version of v6, and v2 was a mistake.
+
+see also: [creative use of v1's MAC address field](https://cohost.org/twilight-sparkle/post/1010833-related-reading-on), [current RFC draft status and other notes](https://cohost.org/iliana/post/1013189-some-notes-on-furthe), [bluetooth doing crimes](https://cohost.org/vikxin/post/1014175-and-then-bluetooth-h)
+
+in conclusion,
+
+# UUIDs nuts.
+
diff --git a/_posts/2023-05-23-two-heresies-about-link-rot.md b/_posts/2023-05-23-two-heresies-about-link-rot.md
new file mode 100644
index 0000000..2e9e076
--- /dev/null
+++ b/_posts/2023-05-23-two-heresies-about-link-rot.md
@@ -0,0 +1,42 @@
+---
+title: two heresies about link rot
+---
+
+
+the term itself is fascinating. there is nothing natural or organic about a hyperlink, i've never seen anyone call a working link alive, and yet a broken link is dead and links becoming broken over time is rot. the breaking of a link can, depending on the context, be frustrating, tragic, amusing; this it has in common with the more conventional kind of death. but we recognize that to live is to one day die, and there may be no justice in when or how but no justice can be asked of if. we will not last forever; why should our work? decay exists as an extant form of life, as they say. that iconic post itself doesn't exist anymore, it seems; we keep it alive through active preservation, and if it outlasts all its authors it will be because so many people found it compelling. a former drama youtuber recently removed several of his toxic edgelord videos, and of course they're not gone (and the links themselves may still work, i don't care enough to check) but it's good that he can do at least that much to clean up the cultural mess he helped make. maybe the fact that links can rot is a good thing, actually. may the worst of all our links rot before we do.
+
+but of course, there's a spectrum, and just because the median tumblr post or youtube video deserves ephemerality doesn't mean there's nothing to be said for permanence. if we really could recover dinosaur DNA from mosquitoes trapped in amber, that could be very neat as long as we didn't do anything unwise afterwards. there's always nonprofits volunteering to be the metaphorical amber, but it takes a lot of money to remember everything for all of time, and they have an unfortunate tendency to also use that money to pick losing fights with big industries and get into Web 3.0, plus you only need them after the link has already rotted, so the simplest solution would be for links to just always keep working. the issue with that is that internet domains are like real estate in that you can only ever rent, and if you don't pay then someone else will so goodbye. i've had several domains lapse and immediately be squatted, especially later in grad school when $20 was a silly amount of money to waste to preserve the domain for a side project i'd long since given up on. links rot because domains expire, and one of the reasons domains expire is that someone else will pay for them if you won't, therefore, if you want to get rid of link rot, you absolutely have to get rid of capitalism.
+
+computers really are a land of contrasts, huh.
+
+# god (derogatory) saw this post and laughed <small>(1 Jun 2023)</small>
+
+![Domain renewal failed - domains deleted
+Domains by Glauca](/assets/2023-05-23-two-heresies-about-link-rot-1.png)
+
+my domain registrar deleted pig.observer with no warning, after sending me an email a few weeks ago that said the renewal was successful. i contacted support and they gave it back, though.
+
+i hadn't decided whether i actually think domain expiration is a bad thing or not - i briefly had a digression about that in the original post but i took it out for concision - but now that it has happened to a thing i still care about and that still has users, i am officially anti-domain-expiration.
+
+also the site is still down, because i haven't been able to log in and fix the NS records, because i can't connect to their control panel. and i can't ping it from my home internet, or from a datacenter in Los Angeles, or from a datacenter in London, so i think they may have fucked up their network configuration. does anybody have DNS registrar recommendations that actually support a reasonable set of TLDs? if i can't have botto.ms and pig.observer on a single professional registrar i'm going to shit a brick and cry.
+
+# changed my mind again domain expiration is funny and therefore good <small>(2 Jun 2023)</small>
+
+<div class="cohost-style-embed">
+{% renderTemplate "webc" %}
+<opengraph-embed
+ href="https://www.vice.com/en/article/4a3xe9/maryland-license-plates-now-inadvertently-advertising-filipino-online-casino"
+ site-href="https://www.vice.com"
+ site-favicon="https://www.vice.com/wp-content/uploads/sites/2/2024/06/cropped-site-icon-1.png?w=32"
+ img-src="https://www.vice.com/wp-content/uploads/sites/2/2023/05/1685481116924-s-l1600-1.png"
+ datetime="2023-05-31T13:00:00+00:00"
+>
+<span slot="title">Maryland License Plates Now Inadvertently Advertising Filipino Online Casino</span>
+A URL on the license plates of 800,000 Maryland cars now redirects to an online casino based in the Philippines.
+<span slot="site-name">VICE</span>
+<span slot="site-domain">vice.com</span>
+<span slot="date">May&nbsp;5,&nbsp;2023</span>
+</opengraph-embed>
+{% endrenderTemplate %}
+<div class="cohost-style-embed-link"><a href="https://www.vice.com/en/article/4a3xe9/maryland-license-plates-now-inadvertently-advertising-filipino-online-casino">https://www.vice.com/en/article/4a3xe9/maryland-license-plates-now-inadvertently-advertising-filipino-online-casino</a></div>
+</div>
diff --git a/_posts/2023-06-15-the-derivative-gardens-license.md b/_posts/2023-06-15-the-derivative-gardens-license.md
new file mode 100644
index 0000000..d867f3f
--- /dev/null
+++ b/_posts/2023-06-15-the-derivative-gardens-license.md
@@ -0,0 +1,18 @@
+---
+title: the Derivative Gardens Misattribution-OnlyCommercial-ShareUnlike 6.9 Unportable License
+description: an anti-license
+---
+
+### You are free to:
+
+- **Share** — copy and redistribute the material in any medium or format
+
+- **Adapt** — remix, transform, and build upon the material
+
+### Under the following terms:
+
+- **Misattribution** — You must give slightly inaccurate credit and provide a link to the wrong license. You may do so in any unreasonable manner.
+
+- **OnlyCommercial** — You may not use the material for noncommercial purposes.
+
+- **Additional restrictions** — You must apply legal terms or technological measures that legally restrict others from doing one weirdly specific thing the license permits.
diff --git a/_posts/2023-08-17-25-hour-time.md b/_posts/2023-08-17-25-hour-time.md
new file mode 100644
index 0000000..477b6dd
--- /dev/null
+++ b/_posts/2023-08-17-25-hour-time.md
@@ -0,0 +1,54 @@
+---
+title: 25-Hour Time (and the Secret Third Half of the Day)
+---
+
+you know how if you're up past midnight, on some level it's still the same day until you go to bed, no matter what the calendar says? well, if you've ever wished that there was notation to unambiguously refer to a current date and time when the current date is somewhat vibes-based, you're actually in luck, because this is a solved problem, although depending on your preferred time notation it may require some creative extension.
+
+## It Came from Public Transit
+
+<small>(Opinions, as always, are my own and not that of my employer.)</small>
+
+Some public transit systems run 24-hour service, but many shut down for a bit overnight, which is less convenient for riders but gives staff some time to reset and maybe even take care of some small maintenance tasks without disrupting any scheduled trips. Denver's D line trains, for example, start at 3:48 AM and end at 12:21 AM the next morning (on weekdays, at least). This creates some interesting problems, because if you spell "12:21 AM the next morning" as `12:21 AM`, it looks like it's before `3:48 AM`, but it isn't, so you need to spell that differently.
+
+Conveniently, this problem is solved in the¹ standard for public transit schedule data, [GTFS](https://en.wikipedia.org/wiki/GTFS). It's a machine-facing interchange format, so it uses 24-hour time for parsing simplicity, so it spells "3:48 AM" as `03:48` and "1:30 PM" as `13:30`². The way it handles times the next morning is extremely simple: if "11:59 PM" is `23:59`, then "12:00 AM the next morning" is `24:00`, and "1:13 AM the next morning" is `25:13`, and I'm writing this sentence at "2:14 AM the next morning", or `26:14`. [Apparently](https://en.wikipedia.org/wiki/24-hour_clock#Times_after_24:00), this is occasionally done in countries that use 24-hour time by businesses that run past midnight.
+
+If you say "oh yeah, i wrote that at 2023-08-16 26:20", even if people aren't familiar with beyond-24-hour time, they'll probably figure out what you mean.
+
+## Welcome to Arco AM/PM Mini-Market
+
+Unless they don't grok 24-hour time at all, like me. A trick like that doesn't really work as nicely with 12-hour time - the minute after `11:59` is already `12:00`, and by the time `12:59` rolls over to `1:00` you're an hour deep into the next half of the day anyway. If you want to have times the next morning in 12-hour time, you have to reach a little deeper into the notation.
+
+A system I was dealing with at work has a really nice solution to this. For space efficiency, it spells "11:30 AM" as `1130a` and "9:15 PM" as `915p`, and then the minute after `1159p` is `1200x`, which I suppose would expand out to "12:00 XM" but I prefer with just the `x`. For sheer intuitive clarity, it doesn't match the 25-hour solution — `x` as an abbreviation for "AM the next morning" is not something you'd be likely to just guess — but if you see it in a list of times with some `a`s and then some `p`s and then some `x`s it's not hard to guess that that's what it means. I have no idea if this sort of thing (or some other solution to this problem) is common outside my specific job.
+
+If you say "I wrote this sentence on 2023-08-16 at 229x", people will only have a clue what you mean if they're already familiar with this concept. Most people won't be, but if you're taking notes for yourself, you will be.
+
+## Completely Missing the Point of Everything
+
+But this is Cohost, and we are no strangers to goofy time notation here. I am not, myself, a .beat time enjoyer, but I know it's a feature and I think it's got several users at varying levels of irony. One of the main things I don't like about .beat time is that it also alienates you from the current date, but we're aggressively solving that in other notations, so can we solve it here too?
+
+25-hour time demonstrates that it can make sense to reach past the bounds of the time system to express times past the edge of the calendar date; there is no authority who can stop us from doing the same thing to .beat time. I'm writing this on 2023-08-16 at @1400 (which mere mortals might write 2023-08-17 @400).
+
+Terrifyingly, on account of time zones stretching in both directions, this could allow for someone west of Switzerland to experience **negative .beat time**. By my math (and the math on [SwatchClock.com](http://www.swatchclock.com/convertTime.php)), someone waking up in Sydney, Australia on 2023-08-17 at 8:00 AM local time would conventionally write that as 2023-08-16 @958 but could instead write it as 2023-08-17 @-042.
+
+The entire point of .beat time is to be absolute and global, and the whole point of this endeavor of vibes-based current date is to be anthropocentric and subjective, so this borders on heresy. In addition, it is almost completely useless as a way of communicating anything to anybody - positive overflow is at least trivial mental math to do, but turning a negative .beat time into a normal .beat time would be, at least for me, in that perfect sweet spot where it's too simple to pull up a calculator but not simple enough to be confident that I'd get the right answer doing it mentally. If you have .beat time enjoyer friends, you can probably ruin their day with a negative .beat time, but that's as much use as anyone will get out of this concept.
+
+## Exiting the Target Audience
+
+“But Cactus,” I hear you ask, “isn't this lopsided towards people who stay up inadvisably late? What about people who wake up inadvisably early? Don't they deserve wacky time notation, too?”
+
+Nope!
+
+Well, that's not fair. To be more specific:
+
+1. If you want to do negative time in 25-hour time, what's the minute before midnight? `00:-01`? `-01:59`? Both of those make me sad.
+2. Coming up with a secret fourth abbreviation for "PM the night before" is probably not difficult, but there's no canonical right answer there.
+3. Negative .beat time could cover this use case anyway, and also very much shouldn't.
+4. You're into real sickos territory by the time you're waking up as early as 4am, and that's still four hours away from needing anything like this. By contrast, staying up until like 1230x, which is in the range that benefits from this, is not really that out there.
+
+Unfortunately, it is now 27:05 / 305x / @1420 (nice), and I need to go the fuck to bed.
+
+---
+
+1. or at least *a* standard: as I recall, there are several standards for public transit schedule data, and different ones are popular in different parts of the world; GTFS is big in the US
+
+2. strictly speaking, those would be `03:48:00` and `13:30:00` on account of seconds also existing, but that's not relevant here. also not relevant here is the way GTFS avoids getting pranked by DST transitions; if you're curious and/or bored, look that one up.
diff --git a/_posts/2023-11-26-tiny-cactus-cloudtest02.md b/_posts/2023-11-26-tiny-cactus-cloudtest02.md
new file mode 100644
index 0000000..3ff3c45
--- /dev/null
+++ b/_posts/2023-11-26-tiny-cactus-cloudtest02.md
@@ -0,0 +1,29 @@
+---
+title: i got ⋖Builder of the Realm⋗ on the cloud DC
+description: a journey
+---
+
+![FFXIV character
+Tiny Cactus «Lost»
+⋖Builder of the Realm⋗
+with all crafting and gathering classes at or above level 50](/assets/2023-11-26-tiny-cactus-cloudtest02-1.png)
+
+i had hoped to get ⋖Honorary Academic⋗ but obviously that's not happening. also, it's basically impossible to finish the lv50 quests since they all require tier 3 combat materia which nobody has (i tried transmuting but it's very inefficient so i didn't get anything good). however, i did still level all the DoH/DoL through ARR in less than a week.
+
+never do this.
+
+if you aren't aware, FFXIV is testing a new cloud data center, and it opened last Monday and it gets deleted this Monday (i.e. tomorrow). they give you a boost to lv 80 for all the combat classes, but not for the crafters and gatherers, so i somehow convinced myself it'd be funny to get an achievement for leveling up my crafters and gatherers on a data center that dies soon.
+
+i'm gonna miss Tiny Cactus🌸Cloudtest02.
+
+# update: i don't have to miss Tiny Cactus🌸Cloudtest02 <small>(27 Nov 2023)</small>
+
+![Tiny-cactus standing next to a Summoning Bell](/assets/2023-11-26-tiny-cactus-cloudtest02-2.png)
+
+with the power of retainer fantasia, Tiny-cactus lives to fish another day. almost cried a little bit hanging out in [the last area of ShB] for the last couple minutes
+
+# don't talk to me or my distant cousin i rescued from a crumbling world ever again <small>(1 Dec 2023)</small>
+
+![a Lalafell and a Miqo'te standing next to each other](/assets/2023-11-26-tiny-cactus-cloudtest02-3.png)
+
+shout out to my FC for letting me swap out one of the retainers in the front yard
diff --git a/_posts/2023-12-27-no-mans-sky-unless.md b/_posts/2023-12-27-no-mans-sky-unless.md
new file mode 100644
index 0000000..10e2f9a
--- /dev/null
+++ b/_posts/2023-12-27-no-mans-sky-unless.md
@@ -0,0 +1,20 @@
+---
+title: No Man’s Sky …unless?
+description: a review
+---
+
+![NO MAN’S SKY …unless?](/assets/2023-12-27-no-mans-sky-unless-1.png)
+
+i chose to build a hazard control room instead of a tavern in my settlement; my citizens aren’t very happy, but my colony was in debt. i don’t speak the language very well, though, so when i talk to the citizens i don’t know what they’re saying. and it’s not particularly my colony, so much as i saved them from Sentinels one time and was immediately elected mayor. the second decision i had to make as overseer of the colony was between the same pair of buildings again.
+
+i sent my freighter on a mission doing satan knows what. it said it’d take an hour and a half real time, so they’re probably back now. and it's not like i built or scavenged the ship; i saved the existing crew from pirates one time and the admiral was like “hello would you like to command my ship”. the last time this happened, i said to just pay me instead, because i could not fathom why anyone would turn over command of their ship to a random stranger whose sole qualifications are saving them from pirates one time, and i suspected the ship command mechanics would be thematically inconsistent and somewhat janky; it turns out you can command an entire fleet of freighters and a squadron of smaller ships.
+
+i’ve said before that half of Dragon Age: Inquisition would be the best video game of all time. i don’t know if i’d go that far at this point, but it’s certainly got a lot of good parts and a lot of extra cruft that distracts from those good parts. and when i think about Dan Olson’s [Alone in Public](https://youtu.be/8ymRN6cCd0I) (and, as i’ve just also discovered, Hbomb’s [THE NO MAN’S SKY RANT](https://youtu.be/4DhaUe6y-Co)) and i compare it to the experience i’m having seven years later, i think of cruft, and systems that add Content™ but don’t add anything meaningful, and potential wasted not by underdelivering but by adding filler to something good, and Dragon Age: Inquisition.
+
+i also think of George Lucas. because the game that Dan and Hbomb played doesn’t exist anymore. the settlement system was added in [Update 3.6, FRONTIERS](https://www.nomanssky.com/frontiers-update/), in September 2021. the Anomaly, a teleporting space station that acts as a hub for some of the overarching story and mechanical progression, has a dozen or so other players running around in it at any given time, sending the framerate and the themes equally to hell; i’m not quite sure how it worked at launch, but the player limit was raised to 16 in [Update 2.0, BEYOND](https://www.nomanssky.com/beyond-update/), in August 2019. the freighter fleet mechanics, including the real-time missions, were added in [Update 1.5, NEXT](https://www.nomanssky.com/next-update/), in July 2018. a lot of the bad filler has been added over time. not every patch has been a change for the worse, and i’m sure you could make a case that on balance the game as it stands now is better than it was at launch, but something has certainly been lost, and not merely lost, but erased after release by an author not content to stay dead. and that erasure began in [Update 1.1, FOUNDATION](https://www.nomanssky.com/foundation-update/), in November 2016, with base building.
+
+my home base employs four total NPCs. the most confusing was the first hire, the overseer; surely it would make more sense for an NPC to oversee the settlement full of NPCs and me to oversee my own base, rather than me overseeing a settlement full of NPCs whose language i do not speak but having to hire an NPC to oversee the base i am building my damn self. my science, weapons, and farming experts are all fairly reasonable by comparison, although they all always have quests for me to do and the rewards are frequently blueprints i already unlocked by other means. one of the first things the game suggested i build at my home base was a teleporter, which renders distance itself meaningless after the first journey to a new solar system. i’ve built several other bases consisting exclusively of teleporters, because the convenience of fast travel is too hard to ignore even in a game that so many people have loved for the slow pace of travel. i don’t think all of these systems were added in FOUNDATION, but the first step into base building was a step towards this.
+
+my weapons expert, when giving me some quest or other, said i had to fight the Sentinels so it’d be “no man’s sky but ours”. and yeah, having a home base in the first place, carving out a piece of the world in which i specifically belong, undermines not just the themes that people connected with in the game as it released but the very goddamn title of the video game. what Dan and Hbomb played and loved was a game that’s about an adventure that can never pause, always moving to the next place but not belonging there either, some planets more hostile but no planets really comfortable, permanently inbetween. a lonely liminality, if you will.
+
+what i’m playing is a game that used to be about all that. and it’s fine.
diff --git a/_posts/2023-12-31-the-browser-is-a-terrible-place-for-art.md b/_posts/2023-12-31-the-browser-is-a-terrible-place-for-art.md
new file mode 100644
index 0000000..f06cc99
--- /dev/null
+++ b/_posts/2023-12-31-the-browser-is-a-terrible-place-for-art.md
@@ -0,0 +1,24 @@
+---
+title: the browser is a terrible place for art
+---
+
+condensation on the shower door is a more stable platform to develop for than the web.
+
+i’ve grumbled repeatedly before about how the web’s lack of actual versioning is a nightmare hellscape from satan, but i may as well rehash that even though it’s not the thing i’m mad about now. Java 9, for example, adds some features that were not present in Java 8, and you can decide whether to develop for Java 9 and be able to use the new features or develop for Java 8 and be compatible with older runtimes. on the web, meanwhile, we have terms like “ES2023” that are purely decorative and carry basically no meaning. all the standards are living documents, new features go in one at a time whenever it’s convenient, and they get implemented one at a time at whatever pace happens, except when a browser can’t figure out how to put a good UI on a new feature so they decide that feature is actually evil¹. the standard way to manage this is to compile your new-feature-using code into older-feature-using code based on guessing which browsers people still use and checking massive tables of which browsers support which features as of which versions, but this sucks, and no amount of vehicular manslaughter² will let you do the same thing in CSS, where you just can’t use anything invented after like 2016 because some dipshit vendor still can’t be bothered to implement it. they actually kinda had “CSS3” (along with “HTML5” and “ES6” to some extent), but the CSS people actually noticed that named standards versions are fake and split CSS up into shit like CSS Media Queries Level 3 and CSS Color Level 4. unfortunately, that hasn’t actually solved any of this, because then Firefox 101 implements like 80% of CSS Values and Units Level 4 and there’s no way to reason about which 80% without just listing off each individual feature by name.
+
+the thing i’m mad about today is that even when you somehow manage to beat the odds and make something that actually works, browsers will break it before long anyway because they don’t give a shit. [an art game](https://boringcactus.itch.io/time-is-a-cruel-mistress) i made less than two years ago just completely fails to do anything now, despite having worked at the time. the game uses the `localStorage` API to do literally anything at all, and apparently using `localStorage` in a game that gets embedded in an iframe sets off a dozen warning sirens at Mozilla HQ and throws an exception that just breaks the game. this game has more CSS than JS (by lines, if not by characters), so it blew my mind when i went to check how i had built it and it just didn’t work at all. i have no idea if i have turned on an inadvisable Firefox setting to break everything all of the time, or if this issue exists the same way in Chrome, or if it's somehow itch.io’s fault for confusing CSP reasons and i’m too eager to assume it’s the browsers’ fault, but like. browsers already all did this on purpose with moving audio playback behind less than obvious thresholds of user interaction over the objections of a ton of people whose browser-based art would just detonate if they did that; they have not earned the benefit of the doubt here.
+
+it’s not just my dubious art games, either; you can’t play the equally sophisticated but much more fun [Room of 1000 Snakes](https://arcanekids.com/snakes) anymore, because steve jobs killed the unity web player when he killed flash and java³.
+
+browsers don’t give a shit about backwards compatibility⁴. operating systems do⁵. make actual executables that can be downloaded and then played. my next game will be distributed solely via retail CD⁶. good fucking luck.
+
+---
+
+1. Mozilla on Web NFC. this is uncharitable but i do not think it is inaccurate
+2. core-js. this is irrelevant but based on the way the guy talks about it this is my own personal [the onion john lennon](https://www.theonion.com/man-always-gets-little-rush-out-of-telling-people-john-1819578998)
+3. obviously we don’t get to check in on the universe where safari on ios supports plugins to see how flash and java are doing in there, and it’s possible that goddamn adobe and motherfucking oracle would ruin everything even if apple didn’t move first. but i’m right
+4. unless they’re doing API design and it’s contains/includes time. goddamn mootools or prototypejs or whichever. if it’s an opportunity to make things worse, they will absolutely care about backwards compatibility. don’t get me started on css if/when
+5. except when they don’t, like if they’re mobile operating systems run by bored corporations, or if apple hasn’t made enough unforced errors yet this year, or if maintaining a 32-bit userland is getting annoying. so basically it’s just windows and the kinds of linux distribution that solve backwards compatibility by never moving forwards in the first place
+6. no it won’t
+7. ⁸ one of my other browser-based games is also broken but because it uses a primary server for multiplayer and that primary server was on the heroku free tier and i hardcoded the url because the previous url was getting caught up in ad blocking because apparently third-party websockets connections to the goofy donuts ass tlds like .fun are inherently suspicious. it could be fixed if i cared, but. there’s the rub
+8. this footnote does in fact not actually come from anywhere, i just wanted to also mention it because it’s tangentially related
diff --git a/_posts/2024-09-08-abdication-is-not-simplicity.md b/_posts/2024-09-08-abdication-is-not-simplicity.md
new file mode 100644
index 0000000..05d1979
--- /dev/null
+++ b/_posts/2024-09-08-abdication-is-not-simplicity.md
@@ -0,0 +1,25 @@
+---
+title: Abdication Is Not Simplicity, or cat -v Considered Harmless
+---
+
+in some sense, the [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) programming language is extremely simple. it only has eight instructions! an intermediate programmer could write an interpreter in an afternoon! that's so simple it borders on trivial! specifically, Brainfuck is simple to *implement*.
+
+*using* Brainfuck, on the other hand, is so self-evidently a bad idea that it's the entire point. even [the Wikipedia “hello world” snippet](https://en.wikipedia.org/wiki/Brainfuck#Hello_World!) would be no small task to independently discover (and even [more direct ways to print “hello world”](https://github.com/ZakiPedio/HelloWorld-in-Brainfuck/blob/main/HelloWorldBrainFuck.bf) are a bit of a mess). there is still a lot of complexity, it’s just been moved downstream, out of the implementer's hands and into the user's.
+
+it'd be absurd to claim that Brainfuck is simple, because the only real way to get any nontrivial work done in Brainfuck would be to find or create a programming language that compiles into Brainfuck, at which point Brainfuck adds nothing. there are things we reasonably expect programming languages to do, and a simple language might do them simply but Brainfuck simply doesn’t do them. i think it'd be unhelpful and misleading to call that “simplicity” when it's just not fulfilling the responsibilities that we generally expect programming languages to fulfill.
+
+fortunately, nobody actually says Brainfuck is simple. unfortunately, however, the idea that “simple” means “simple to implement, regardless of how complicated it is to use” is a long-lived meme among certain kinds of programmers. one cluster of such programmers is called [suckless](https://suckless.org/), and their backwards understanding of simplicity leads to fascinating decisions like “[the way you change the settings in this software is by editing `config.h` and recompiling it](https://dwm.suckless.org/customisation/)”. it's [software that gatekeeps itself](https://dwm.suckless.org/):
+
+> Because dwm is customized through editing its source code, it's pointless to make binary packages of it. This keeps its userbase small and elitist. No novices asking stupid questions. There are some distributions that provide binary packages though.
+
+this sucks more than [systemd or cmake or any of the software they’re butthurt about](https://suckless.org/sucks/) ever could.
+
+there's a semi-overlapping cluster of annoying fossbro nonsense over on [cat-v.org](https://cat-v.org/). some of it is [the same boomer nonsense about old software good new software bad](https://harmful.cat-v.org/software/), and some of it is more directly venerating Rob Pike and The UNIX Philosophy™. the website is named after [a talk Rob Pike gave in 1983](https://harmful.cat-v.org/cat-v/), “UNIX Style, or cat -v Considered Harmful”. that page also links to [a paper](https://harmful.cat-v.org/cat-v/unix_prog_design.pdf) by Rob Pike and Brian Kernighan, which is a really interesting case study in The UNIX Philosophy™.
+
+what is `cat`? if you ask someone who knows a bit about the command line on macOS or Linux, they’ll tell you it displays the contents of a file, but if you ask a proper UNIX dweeb they’ll tell you it *concatenates* files (hence the name) and it’s a happy accident that it’ll display the contents of a single file. as Pike and Kernighan put it,
+
+> The fact that cat will also print on the terminal is a special case. Perhaps surprisingly, in practice it turns out that the special case is the main use of the program.
+
+and right away we have encountered a flaw in the UNIX Philosophy™ tenet that a program should do one thing well. `cat` does two things well: concatenating files and displaying them. a program that displays files well would very reasonably benefit from options to add line numbers or display non-printing characters (in BSD, `cat -s` and the titular `cat -v`), but Pike and Kernighan are right that a program that concatenates files well would need no such options.
+
+but if displaying a file is the main use of `cat`, then it is absurd to argue that displaying a file is not the one thing it should do well. Pike and Kernighan suggest adding line numbers with `awk` and displaying non-printing characters with a new program `vis`, to maintain the purity of `cat` for concatenating files, but that sucks. `cat` is responsible for displaying files, and as such if it can’t meet reasonable requests about displaying files, that’s not simplicity, that’s an abdication of that responsibility. `cat -v` is good, and 1983 Rob Pike was wrong, and The UNIX Philosophy™ is bogus.
diff --git a/_posts/2024-09-20-eggbug-forever-ffxiv.md b/_posts/2024-09-20-eggbug-forever-ffxiv.md
new file mode 100644
index 0000000..f916b5e
--- /dev/null
+++ b/_posts/2024-09-20-eggbug-forever-ffxiv.md
@@ -0,0 +1,28 @@
+---
+title: "Eggbug Forever: a custom minion mod for FFXIV"
+description: In memory of https://cohost.org. The real eggbug is the friends we made along the way. We carry him with us forever.
+---
+
+![a purple haired catgirl /showleft-ing to highlight eggbug floating in the air](/assets/2024-09-20-eggbug-forever-ffxiv-1.png)
+
+The real eggbug was the friends we made along the way. We carry him with us forever.
+
+A very simple import of Xenon Fossil’s [low-poly eggbug model](https://cohost.org/xenonfossil/post/7629261-https-xenonfossil) replacing the Wind-up Airship and/or the Great Serpent of Ronka (the Great Serpent animations are adorable but the rigging is a little janky so the Wind-up model may be better for gposing).
+
+[XIV Mod Archive](https://www.xivmodarchive.com/modid/117001) | [Heliosphere](https://heliosphere.app/mod/qbmgcyzy3n49dc90djpppegp0c)
+
+---
+
+# <small>(30 Sep 2024)</small>
+
+<div style="display: flex; flex-flow: row; align-items: center">
+<img alt="eggbug wiggling and bouncing around next to a catgirl sitting on the ground in ffxiv" src="/assets/2024-09-20-eggbug-forever-ffxiv-2.gif" style="max-width: 50%" /><img alt="eggbug bouncing along behind a catgirl running towards the camera in ffxiv" src="/assets/2024-09-20-eggbug-forever-ffxiv-3.gif" style="max-width: 50%" />
+</div>
+
+eggbug forever. see y’all around.
+
+<div style="font-family: 'Atkinson Hyperlegible', sans-serif; font-size: 0.875rem; line-height: 1.25rem; color: #686664">
+
+[#ffxiv](https://cohost.org/cactus/tagged/ffxiv) [#eggbug](https://cohost.org/cactus/tagged/eggbug) [#Goodbye cohost](https://cohost.org/cactus/tagged/Goodbye%20cohost) [#last one out hit the lights](https://cohost.org/cactus/tagged/last%20one%20out%20hit%20the%20lights) [#but for real this time](https://cohost.org/cactus/tagged/but%20for%20real%20this%20time)
+
+</div>
diff --git a/_posts/_posts.11tydata.js b/_posts/_posts.11tydata.js
index 2e07a0e..bc6ccb4 100644
--- a/_posts/_posts.11tydata.js
+++ b/_posts/_posts.11tydata.js
@@ -38,6 +38,7 @@ export default {
}
switch (child.type) {
case "text":
+ case "code_inline":
firstParagraph += child.content;
break;
case "softbreak":