Can AI retroactively fix WordPress tags?

I’ve a notion that during 2025 I might put some effort into tidying up the tagging taxonomy on my blog. There’s a few tags that are duplicates (e.g. ai and artificial intelligence) or that exhibit significant overlap (e.g. dog and dogs), or that were clearly created when I speculated I’d write more on the topic than I eventually did (e.g. homa night, escalators1, or nintendo) or that are just confusing and weird (e.g. not that bacon sandwich picture).

Cloud-shaped wordcloud of tags used on DanQ.me, sized by frequency. The words "geocaching" and "cache log" dominate the centre of the picture, with terms like "fun", "funny", "geeky", "news", "video games", "technology", "video", and "review" a close second.
Not an entirely surprising word cloud of my tag frequency, given that all of my cache logs are tagged “cache log” and “geocaching”, and relatively-generic terms like “technology”, “fun”, and “funny” appear all over the place on my blog.

Retro-tagging with AI

One part of such an effort might be to go back and retroactively add tags where they ought to be. For about the first decade of my blog, i.e. prior to around 2008, I rarely used tags to categorise posts. And as more tags have been added it’s apparent that many old posts even after that point might be lacking tags that perhaps they ought to have2.

I remain sceptical about many uses of (what we’re today calling) “AI”, but one thing at which LLMs seem to do moderately well is summarisation3. And isn’t tagging and categorisation only a stone’s throw away from summarisation? So maybe, I figured, AI could help me to tidy up my tagging. Here’s what I was thinking:

  1. Tell an LLM what tags I use, along with an explanation of some of the quirkier ones.
  2. Train the LLM with examples of recent posts and lists of the tags that were (correctly, one assumes) applied.
  3. Give it the content of blog posts and ask what tags should be applied to it from that list.
  4. Script the extraction of the content from old posts with few tags and run it through the above, presenting to me a report of what tags are recommended (which could then be coupled with a basic UI that showed me the post and suggested tags, and “approve”/”reject” buttons or similar.

Extracting training data

First, I needed to extract and curate my tag list, for which I used the following SQL4:

SELECT COUNT(wp_term_relationships.object_id) num, wp_terms.slug FROM wp_term_taxonomy
LEFT JOIN wp_terms ON wp_term_taxonomy.term_id = wp_terms.term_id
LEFT JOIN wp_term_relationships ON wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
WHERE wp_term_taxonomy.taxonomy = 'post_tag'
AND wp_terms.slug NOT IN (
  -- filter out e.g. 'rss-club', 'published-on-gemini', 'dancast' etc.
  -- these are tags that have internal meaning only or are already accurately applied
  'long', 'list', 'of', 'tags', 'the', 'ai', 'should', 'never', 'apply'
)
GROUP BY wp_terms.slug
HAVING num > 2 -- filter down to tags I actually routinely use
ORDER BY wp_terms.slug
Many of my tags are used for internal purposes; e.g. I tag posts published on gemini if they’re to appear on gemini://danq.me/ and dancast if they embed an episode of my podcast. I filtered these out because I never want the AI to suggest applying them.

I took my output and dumped it into a list, and skimmed through to add some clarity to some tags whose purpose might be considered ambiguous, writing my explanation of each in parentheses afterwards. Here’s a part of the list, for example:

Prompt derivation

I used that list as the basis for the system message of my initial prompt:

Suggest topical tags from a predefined list that appropriately apply to the content of a given blog post.

# Steps

1. **Read the Blog Post**: Carefully read through the provided content of the blog post to identify its main themes and topics.
2. **Analyse Key Aspects**: Identify key topics, themes, or subjects discussed in the blog post.
3. **Match with Tags**: Compare these identified topics against the list of available tags.
4. **Select Appropriate Tags**: Choose tags that best represent the main topics and themes of the blog post.

# Output Format

Provide a list of suggested tags. Each tag should be presented as a single string. Multiple tags should be separated by commas.

# Allowed Tags

Tags that can be suggested are as follows. Text in parentheses are not part of the tag but are a description of the kinds of content to which the tag ought to be applied:

- aberdyfi
- aberystwyth
- ...
- youtube
- zoos

# Examples

**Input:**
The rapid advancement of AI technology has had a significant impact on my industry, even on the ways in which I write my blog posts. This post, for example, used AI to help with tagging.

**Output:**
ai, technology, blogging, meta, work

...(other examples)...

# Notes

- Ensure that all suggested tags are relevant to the key themes of the blog post.
- Tags should be selected based on their contextual relevance and not just keyword matching.

This system prompt is somewhat truncated, but you get the idea.

Now I was ready to give it a go with some real data. As an initial simple and short (and therefore also computationally cheap) experiment, I tried feeding it a note I wrote last week about the interrobang’s place in the Spanish language, and in Unicode.

That post already has the following tags (but this wasn’t disclosed to the AI in its training set; it had to work from scratch): , , (a bit of a redundancy there!), , and .

Testing it out

Let’s see what the AI suggests:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_TOKEN" \
  -d '{
  "model": "gpt-4o-mini",
  "messages": [
    {
      "role": "system",
      "content": [
        {
          "type": "text",
          "text": "[PROMPT AS DESCRIBED ABOVE]"
        }
      ]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "My 8-year-old asked me \"In Spanish, I need to use an upside-down interrobang at the start of the sentence‽\" I assume the answer is yes A little while later, I thought to check whether Unicode defines a codepoint for an inverted interrobang. Yup: ‽ = U+203D, ⸘ = U+2E18. Nice. And yet we dont have codepoints to differentiate between single-bar and double-bar \"cifrão\" dollar signs..."
        }
      ]
    }
  ],
  "response_format": {
    "type": "text"
  },
  "temperature": 1,
  "max_completion_tokens": 2048,
  "top_p": 1,
  "frequency_penalty": 0,
  "presence_penalty": 0
}'
Running this via command-line curl meant I quickly ran up against some Bash escaping issues, but set +H and a little massaging of the blog post content seemed to fix it.

GPT-4o-mini

When I ran this query against the gpt-4o-mini model, I got back: unicode, language, education, children, symbols.

That’s… not ideal. I agree with the tags unicode, language, and children, but this isn’t really about education. If I tagged everything vaguely educational on my blog with education, it’d be an even-more-predominant tag than geocaching is! I reserve that tag for things that relate specifically to formal education: but that’s possibly something I could correct for with a parenthetical in my approved tags list.

symbols, though, is way out. Sure, the post could be argued to be something to do with symbols… but symbols isn’t on the approved tag list in the first place! This is a clear hallucination, and that’s pretty suboptimal!

Maybe a beefier model will fare better…

GPT-4o

I switched gpt-4o-mini for gpt-4o in the command above and ran it again. It didn’t take noticeably longer to run, which was pleasing.

The model returned: children, language, unicode, typography. That’s a big improvement. It no longer suggests education, which was off-base, nor symbols, which was a hallucination. But it did suggest typography, which is a… not-unreasonable suggestion.

Neither model suggested spain, and strictly-speaking they were probably right not to. My post isn’t about Spain so much as it’s about Spanish. I don’t have a specific tag for the latter, but I’ve subbed in the former to “connect” the post to ones which are about Spain, but that might not be ideal. Either way: if this is how I’m using the tag then I probably ought to clarify as such in my tag list, or else add a note to the system prompt to explain that I use place names as the tags for posts about the language of those places. (Or else maybe I need to be more-consistent in my tagging).

I experimented with a handful of other well-tagged posts and was moderately-satisfied with the results. Time for a more-challenging trial.

This time, with feeling…

Next, I decided to run the code against a few blog posts that are in need of tags. At this point, I wasn’t quite ready to implement a UI, so I just adapted my little hacky Bash script and copy-pasted HTML-stripped post contents directly into it.

Hand-drawn wireframe application with a blog post shown on the left (with 'previous' and 'next' buttons) and proposed tags on the right (with 'accept' and 'reject' buttons), alongside conventional tag management tools.
If it worked, I decided, I could make a UI. Until then, the command line was plenty sufficient.

I ran against three old posts:

Hospitals (June 2006)

In this post, I shared that my grandmother and my coworker had (independently) been taken into hospital. It had no tags whatsoever.

The AI suggested the tags hospital, family, injury, work, weddings, pub, humour. Which at a glance, is probably a superset of the tags that I’d have considered, but there’s a clear logic to them all.

It clearly picked out weddings based on a throwaway comment I made about a cousin’s wedding, so I disagree with that one: the post isn’t strictly about weddings just because it mentions one.

pub could go either way. It turns out my coworker’s injury occurred at or after a trip to the pub the previous night, and so its relevance is somewhat unknowable from this post in isolation. I think that’s a reasonable suggestion, and a great example of why I’d want any such auto-tagging system to be a human assistant (suggesting candidate tags) and not a fully-automated system. Interesting!

Finally, you might think of humour as being a little bit sarcastic, or maybe overly-laden with schadenfreude. But the blog post explicitly states that my coworker “carefully avoided saying how he’d managed to hurt himself, which implies that it’s something particularly stupid or embarrassing”, before encouraging my friends to speculate on it. However, it turns out that humour isn’t one of my existing tags at all! Boo, hallucinating AI!

I ended up applying all of the AI’s suggestions except weddings and humour. I also applied smartdata, because that’s where I worked (the AI couldn’t have been expected to guess that without context, though!).

Catch-Up: Concerts (June 2005)

This post talked about Ash and I’s travels around the UK to see REM and Green Day in concert5 and to the National Science Museum in London where I discovered that Ash was prejudiced towards… carrot cake.

The AI suggested: concerts, travel, music, preston, london, science museum, blogging.

Those all seemed pretty good at a first glance. Personally, I’d forgotten that we swung by Preston during that particular grand tour until the AI suggested the tag, and then I had to look back at the post more-carefully to double-check! blogging initially seemed like a stretch given that I was only blogging about not having blogged much, but on reflection I think I agree with the robot on this one, because I did explicitly link to a 2002 page that fell off the Internet only a few years ago about the pointlessness of blogging. So I think it counts.

Dan, in his 20s, crouches awkwardly in front of a TV and a Nintendo Wii in a wood-panelled room as he attempts to headbutt a falling blue balloon.
I was able to verify that I’d been in Preston with thanks to this contemporaneous photo. I have no further explanation for the content of the photo, though.

science museum is a big fail though. I don’t use that tag, but I do use the tag museum. So close, but not quite there, AI!

I applied all of its suggestions, after switching museum in place of science museum.

Geeky Winnage With Bluetooth (September 2004)

I wrote this blog post in celebration of having managed to hack together some stuff to help me remote-control my PC from my phone via Bluetooth, which back then used to be a challenge, in the hope that this would streamline pausing, playing, etc. at pizza-distribution-time at Troma Night, a weekly film night I hosted back then.

Four young people, smiling in laughing, sit in a cluttered and messy flat.
If you were sat on that sofa, fighting your way past other people and a mango-chutney-barrel-cum-table to get to a keyboard was genuinely challenging!

It already had the tag technology, which it inherited from a pre-tagging evolution of my blog which used something akin to categories (of which only one could be assigned to a post). In addition to suggesting this, the AI also picked out the following options: bluetooth, geeky, mobile, troma night, dvd, technology, and software.

The big failure here was dvd, which isn’t remotely one of my tags (and probably wouldn’t apply here if it were: this post isn’t about DVDs; it barely even mentions them). Possibly some prompt engineering is required to help ensure that the AI doesn’t make a habit of this “include one tag not from the approved list, every time” trend.

Apart from that it’s a pretty solid list. Annoyingly the AI suggested mobile, which isn’t an approved tag, instead of mobiles, which is. That’s probably a tokenisation fault, but it’s still annoying and a reminder of why even a semi-automated “human-checked” system would need a safety-check to ensure that no absent tags are allowed through to the final stage of approval.

This post!

As a bonus experiment, I tried running my code against a version of this post, but with the information about the AI’s own prompt and the examples removed (to reduce the risk of confusion). It came up with: ai, wordpress, blogging, tags, technology, automation.

All reasonable-sounding choices, and among those I’d made myself… except for tags and automation which, yet again, aren’t among tags that I use. Unless this tendency to hallucinate can be reined-in, I’m guessing that this tool’s going to continue to have some challenges when used on longer posts like this one.

Conclusion and next steps

The bottom line is: yes, this is a job that an AI can assist with, but no, it’s not one that it can do without supervision. The laser-focus with which gpt-4o was able to pick out taggable concepts, faster than I’d have been able to do for the same quantity of text, shows that there’s potential here, but it’s not yet proven itself enough of a time-saver to justify me writing a fluffy UI for it.

However, I might expand on the command-line tools I’ve been using in order to produce a non-interactive list of tagging suggestions, and use that to help inform my work as I tidy up the tags throughout my blog.

You still won’t see any “AI-authored” content on this site (except where it’s for the purpose of talking about AI-generated content, and it’ll always be clearly labelled), and I can’t see that changing any time soon. But I’ll admit that there might be some value in AI-assisted curation and administration, so long as there’s an informed human in the loop at all times.

Footnotes

1 Based on my tagging, I’ve apparently only written about escalators once, while playing Pub Jenga at Robin‘s 21st birthday party. I can’t imagine why I thought it deserved a tag.

2 There are, of course, various other people trying similar approaches to this and similar problems. I might have tried one of them, were it not for the fact that I’m not quite as interested in solving the problem as I am in understanding how one might use an AI to solve the problem. It’s similar to how I don’t enjoy doing puzzles like e.g. sudoku as much as I enjoy writing software that optimises for solving such puzzles. See also, for example, how I beat my children at Mastermind or what the hardest word in Hangman is or my various attempts to avoid doing online jigsaws.

3 Let’s ignore for a moment the farce that was Apple’s attempt to summarise news headlines, shall we?

4 Essentially the same SQL, plus WordClouds.com, was used to produce the word cloud grapic!

5 Two separate concerts, but can you imagine‽ 🤣

× × × ×

Sabbatical Lesson #1: Boundaries

Today was my first day back at work after three months of paid leave1. I’d meant to write about the overall experience of my sabbatical and the things I gained from it before I returned, but I’m glad I didn’t because one of the lessons only crystallised this morning.

A French Bulldog wearing a teal jumper pulls away at her red lead as she walks down a dirt path between gardens. Freezing fog hangs in the air up ahead.
This is about the point on the way back from the school run at which I pull out my phone and see what’s happening in the world or at work. But not today.

My typical work schedule sees me wake up some time before 06:30 so I can check my notifications, formulate my to-do list for the day, and so on, before the kids get up. Then I can focus on getting them full of breakfast, dressed, and to school, and when I come back to my desk I’ve already got my day planned-out. It’s always felt like a good way to bookend my day, and it leans into my “early bird” propensities2.

Over the last few years, I’ve made a habit of pulling out my phone and checking for any new work Slack conversations while on the way back after dropping the kids at school. By this point it’s about 08:45 which is approximately the time of day that all of my immediate teammates – who span five timezones – have all checked-in. This, of course, required that I was signed in to work Slack on my personal phone, but I’d come to legitimise this bit of undisciplined work/life-balance interaction by virtue of the fact that, for example, walking the dog home from the school run was “downtime” anyway. What harm could it do to start doing “work” things ten minutes early?

Dan, wearing a purple t-shirt, looks at the camera while pointing at the centre of three computer screens which share a cluttered desk, each of which shows a stylised image version of the Automattic Creed.
Here. Here is where work happens (or, y’know, anywhere I take my work laptop to… but the crucial thing is that work has a time and a place, and it doesn’t include “while walking the dog home after dropping the kids at school”).

But walking the dog isn’t “downtime”. It’s personal time. When I’m looking at your phone and thinking about work I’m actively choosing not to be looking at the beautiful countryside that I’m fortunate enough to be able to enjoy each morning, and not to be thinking about… whatever I might like to be thinking about! By blurring my work/life-balance I’m curtailing my own freedom, and that’s bad for both my work and personal lives!

My colleague Kyle recently returned from six months of parental leave and shared some wisdom with me, which I’ll attempt to paraphrase here:

It takes some time at a new job before you learn all of the optimisations you might benefit from making to your life. This particular workflow. That particular notetaking strategy. By the time you’ve come up with the best answers for you, there’s too much inertia to overcome for you to meaningfully enact personal change.

Coming back from an extended period of leave provides the opportunity to “reboot” the way you work. You’re still informed by all of your previous experience, but you’re newly blessed with a clean slate within which to implement new frameworks.

He’s right. I’ve experienced this phenomenon when changing roles within an organisation, but there’s an even stronger opportunity, without parallel, to “reboot” your way of working when returning from a sabbatical. I’ve got several things I’d like to try on this second chapter at Automattic. But the first one is that I’m not connecting my personal phone to my work Slack account.

Footnotes

1 My employers’ sabbatical benefit is truly an epic perk.

2 Mysteriously, and without warning, at about the age of 30 I switched from being a “night owl” to being an “early bird”, becoming a fun piece of anecdotal evidence against the idea that a person’s preference is genetic or otherwise locked-in at or soon after birth. As I’ve put it since: “I’ve become one of those chirpy, energetic ‘morning people’ that I used to hate so much when I was younger.”.

× ×

We’ll Prescribe You A Cat by Syou Ishida

Book cover of We'll Prescribe You A Cat by Syou Ishida, translated by E. Madison Shimoda. At the top is written 'The Japanese Bestseller'. The hospital-green cover shows an open pill bottle (with label written in Japanese) pouring out five cats of different breeds who tumble down to land on their feet atop the translator's name.Another book I received at Christmas Eve’s book exchange was We’ll Prescribe You A Cat by Syou Ishida, translated from the original Japanese by Emmie Madison Shimoda. It’s apparently won all kinds of acclaim and awards and what-have-you, so I was hoping for something pretty spectacular.

It’s… pretty good, I guess? Less a novel, it’s more like a collection of short stories with an overarching theme, within which a deeper plot which spans them all begins to emerge… but is never entirely resolved.

That repeating theme might be summed up as this: a person goes to visit a clinic – often under the illusion that it’s a psychiatric specialist – where, after briefly discussing their problems with the doctor, they’re prescribed a dose of “cat” for some number of days. There’s a surprising and fun humour in the prescription, each time: the matter-of-fact way that the doctor dispenses felines as if they were medications and resulting reactions of his nonplussed patients. Fundamentally, a prescription of cat works, and by the time the cat is returned to the clinic, its caretaker is cured, albeit not necessarily in the way in which they would have originally expected.

Standing alone, each chapter short story is excellent. The writing is compelling and rich and the characters well-developed, particularly in the short timeframes in which we get to know each of them. There’s a lot of interesting bits of Japanese culture represented, too, which – as an outsider – piqued my curiosity: whether by the careful work of the author or her translator it never left me feeling lost, although I suspect there might be a few subtler points I missed as a result of my geographic bias1.

The characters (whether human, feline, or… otherwise…?) and their situations are quirky and amusing, and there are a handful of heart-warming… and heart-wrenching… moments that I thoroughly enjoyed. But by the time I was half-way through the book, I was becoming invested in a payoff that would never come to be delivered. The nature of the doctor, his receptionist, and their somewhat-magical clinic is never really resolved, and the interconnections between the patients is close to non-existent, leaving the book feeling like a collection of tales that are related to… but not connected to… one another. As much as I’d enjoyed every story – and I did! – I nonetheless felt robbed of the opportunity to wrap up the theme that they belong to.

Instead, we’re given just more unanswered questions: hints at the nature of the clinic and its occupants, ideas that skirt around ideas of magic and ghosts, and no real explanation. Maybe the author’s planning to address it in the upcoming sequel, but unless I’m confident that’s the case, I’ll probably skip it.

In summary: some beautifully-written short stories with a common theme and a fun lens on Japanese culture, particularly likely to appeal to a cat lover, but with no payoff for getting invested in the overarching plot.

Footnotes

1 Ishida spends a significant amount of intention describing the regional accents of various secondary characters, and comparing those to the Kyoto dialect, for example. I’m pretty sure there’s more I could take from this if I had the cultural foothold to better understand the relevance! But most of the cultural differences are less-mysterious.

×

Small-World Serendipity

As part of our trip to the two-island republic of Trinidad & Tobago, Ruth and I decided we’d love to take a trip out to Buccoo Reef, off the coast of the smaller island. The place we’ve been staying during the Tobago leg of our visit made a couple of phone calls for us and suggested that we head on down to the boardwalk at nearby Buccoo the next morning where we’d apparently be able to meet somebody from Pops Tours who’d be able to take us out1.

Silhouette of a bird flying through lightly-cloudy skies, over a colourful sign which begins "I heart-sign BUC" before disppearing out of frame. The heart is coloured in the red-with-a-black-and-white-diagonal-stripe of the Trinidad & Tobago flag.
I could have shown you a picture of the fun ‘I ♥️ Buccoo’ sign from the boardwalk, but I got distracted by a Magnificent Frigatebird circling overhead2.

At the allotted time, we found somebody from Pops Tours, who said that he was still waiting for their captain to get there3 and asked us to go sit under the almond tree down the other end of the boardwalk and he’d meet us there.

A black chicken and her four young chicks stand on a boardwalk and peck at the tail end of a coconut.
It was only after we left to follow the instructions that I remembered that I don’t know how to identify an almond tree. So we opted to sit under a tree near a chicken teaching her chicks how to eat a coconut4. I still don’t know if that was right, but the boaters found us in the end so it can’t have been too far off.

We’d previously clocked that one of the many small boats moored in the bay was Cariad, and found ourselves intensely curious. All of the other boats we’d seen had English-language names of the kinds you’d expect: a well-equipped pleasure craft optimistically named Fish Finder, a small dual-motorcraft with the moniker Bounty, a brightly-coloured party boat named Cool Runnings, and so on. To travel a third of the way around the world to find a boat named in a familiar Welsh word felt strange.

Small six-seater day boat named 'Cariad', afloat. The letter I is dotted with a heart symbol.
Either you’re an extremely long way from home, boat, or else somebody around here has a surprising interest in the Welsh language.

So imagine our delight when the fella we’d been chatting to came over, explained that their regular tour boat (presumably the one pictured on their website) was in the shop, and said that his cousin would be taking us out in his boat instead… and that cousin came over piloting… the Cariad!

As we climbed aboard, we spotted that he was wearing a t-shirt with a Welsh dragon on it, and a sticker on the side of the helm carried a Welsh flag. What strange coincidence is this, that Ruth and I – who met while living in Wales and come for a romantic getaway to the Caribbean – should happen to find ourselves aboard a literal “love” boat named in Welsh.

View from the prow of the Cariad, a light blue boat, as she heads towards a distant shore.
Long shallow sandbars and reefs almost surround the islands of Trinidad and Tobago, leaving enormous areas accessible only to low-draft boats (and helping to protect the islands from some of the worst of the weather that the Caribbean can muster).

There probably aren’t many boats on Earth that fly both the colours of Trinidad & Tobago and of Wales, so we naturally had to ask: did you name this boat?, and why? It turns out that yes, our guide for the day has a love of and fascination with Wales that we never quite got to the bottom of. He’d taken a holiday to Swansea just last year, and would be returning to Wales again later this year.

It’s strange to think that anybody might deliberately take a holiday from a tropical island paradise to come to drizzly cold Wales, but there you have it. It sounds like he was into his football and that might have had an impact on his choice of destination, but choose to believe that maybe there’s a certain affinity between parts of the world that have experienced historical oppression at the hands of a colonial English mindset? Like: perhaps Nigerians would enjoy India as a getaway destination, or Guyanans would dig Mauritius as a holiday spot, too?5

Dan stands waist-deep in seawater; land is visible in the far distance.
I wrote previously about visiting the Nylon Pool, an waist-deep bit of ocean on a sandbar a full half a mile offshore.

We took a dip at the Nylon Pool, snorkelled around parts of Buccoo Reef (replete with tropical fish of infinite variety and colour), spotted sea turtles zipping around the boat, and took a walk along No Man’s Land (a curious peninsula, long and thin and cut-off from the mainland by mangrove swamps, so-named because Trinidadian law prohibits claiming ownership of any land within a certain distance of the high tide mark… and this particular beach spot consists entirely of such land, coast-to-coast, on account of its extreme narrowness. All in all, it was a delightful boating adventure.

(And for the benefit of the prospective tourist who stumbles upon this blog post in years to come, having somehow hit the right combination of keywords: we paid $400 TTD6 for the pair of us: that’s about £48 GBP at today’s exchange rate, which felt like exceptional value for an amazing experience given that we got the expedition entirely to ourselves.)

A man sits on the prow of the Cariad, over a sandbar, pulling in her anchor.
Any worries I might have had about the seaworthiness of our vessel as its owner repeatedly bailed out the back of the boat with a small bucket were quickly assuaged when I realised that I could probably walk most of the way back to shore, should I need to! (sadly not visible: the Welsh dragon on front of his t-shirt)

But aside from the fantastic voyage we got to go on, this expedition was noteworthy in particular for Cariad and her cymruphile captain. It feels like a special kind of small-world serendipity to discover such immediate and significant common ground with a stranger on the other side of an ocean… to coincide upon a shared interest in a culture and place less-foreign to you than to your host.

An enormous diolch yn fawr7 is due to Pops Tours for this remarkable experience.

Footnotes

1 Can I take a moment to observe how much easier it was to charter a boat in Tobago than it was in Ireland, where I left several answerphone messages but never even got a response? Although in the Irish boat owners’ defence, I was being creepy and mysterious by asking them to take me to random coordinates off the coast.

2 It’s possible that I’ve become slightly obsessed with frigatebirds since arriving here. I first spotted them from our ferry ride from Trinidad to Tobago, noticing their unusually widely-forked tails, striking white (in the case of the females) chests, and relatively-effortless (for a seabird) thermal-chasing flight. But they’re really cool! They’re a seabird… that isn’t waterproof and can’t swim… if they land in the water, they’re at serious risk of drowning! (Their lack of water-resistant feathers helps with their agility, most-likely.) Anyway – while they can snatch shallow-swimming prey out of the water, they seem to prefer to (and get at least 40% of their food from) stealing it from other birds, harassing them in-flight and snatching it from their bills, or else attacking them until they throw up and grabbing their victim’s vomit as it falls. Nature is weird and amazing.

3 Time works differently here. If you schedule something, it’s more a guideline than it is a timetable. When Ruth and I would try paddleboarding a few days later we turned up at the rental shack at their published opening time and hung out on the beach for most of an hour before messaging the owners via the number on their sign. After 15 minutes we got a response that said they’d be there in 10 minutes. They got there 20 minutes later and opened their shop. I’m not complaining – the beach was lovely and just lounging around in the warm sea air with a cold drink from a nearby bar was great – but I learned from the experience that if you’re planning to meet somebody at a particular time here, you might consider bringing a book. (Last-minute postscript: while trying to arrange our next accommodation, alongside writing this post, I was told that I’d receive a phone call “in half an hour” to arrange payment: that was over an hour ago…)

4 Come for the story of small-world serendipity; stay for the copious candid bird photos, I guess?

5 I’ll tell you one thing about coming out to Trinidad & Tobago, it makes you feel occasionally (and justifiably) awkward for the colonial era of the British Empire. Queen Elizabeth II gave royal assent to the bill that granted the islands independence only in 1962, well within living memory, and we’ve met folks who’ve spoken to us about living here when it was still under British rule.

6 Exceptionally-geeky footnote time. The correct currency symbol for the Trinidad & Tobago Dollar is an S-shape with two vertical bars through it, which is not quite the same as the conventional S-shape with a single vertical bar that you’re probably used to seeing when referring to e.g. American, Canadian, or Australian dollars. Because I’m a sucker for typographical correctness, I decided that I’d try to type it “the right way” here in my blog post, and figured that Unicode had solved this problem for me: the single-bar dollar sign that’s easy to type on your keyboard inherits its codepoint from ASCII, I guessed, so the double-bar dollar sign would be elsewhere in Unicode-space, right? Like how Unicode defines single-bar (pound) and double-bar (lira) variants of the “pound sign”. But it turns out this isn’t the case: the double-bar dollar sign, sometimes called cifrão (from Portugese), and the single-bar dollar sign are treated as allographs: they share the same codepoint and only the choice of type face differentiates between them. I can’t type a double-bar dollar sign for you without forcing an additional font upon you, and even if I did it wouldn’t render “correctly” for everybody. Unicode is great, but it’s not perfect.

7 “Thank you very much”, in Welsh, but you probably knew that already.

× × × × × ×

James Acaster’s Classic Scrapes

Book cover of James Acaster's Classic Scrapes.On the flight over to Trinidad I finished reading James Acaster’s Classic Scrapes by James Acaster, which I received as part of our family’s traditional Christmas Eve book exchange. I’m a big fan of his stand-up work (and I maintain that his 2018 serialised show Repertoire is among of the most artfully-crafted pieces of live comedy ever written) and clearly JTA recalled this fact when giving me this book.

Many of the stories in Classic Scrapes have featured in his work before, in various forms, and I found myself occasionally recognising one and wondering if I’d accidentally skipped back a chapter. It helps a lot to read them in Acaster’s “voice” – imagining his delivery – because they’re clearly written to be enjoyed in that way. In the first few chapters the book struggled to “grab” me, and it wasn’t until I started hearing it as if I were listening in to James’s internal monologue that it gave me my first laugh-out-loud moment.

After that, though, it got easier to enjoy each and every tall tale told. Acaster’s masterful callback humour ties together anecdotes about giant letter Ws, repeated car crashes, and the failures of his band (and, I suppose, almost everything else in his life, at some point or another), across different chapters, which is fun and refreshing and adds a new dimension to each that wouldn’t be experienced in isolation.

A further ongoing concept seems to be a certain idolisation of Dave Gorman, whose Are You Dave Gorman? and Googlewhack storytelling style was clearly an inspiration. In these, of course, a series of (mis)adventures with a common theme or mission becomes a vehicle for a personal arc within which the absurdity of the situations described is made accessible and believable. But with James Acaster’s self-deprecating style, this is delivered as a negative self-portrayal: somebody who doesn’t live up to their idea of their own hero, and becomes a parody of themselves for trying. It’s fun, but perhaps not for everybody (I tried to explain to Ruth why I’d laughed out loud at something but then needed to explain to her who Dave Gorman is and why that matters.)

A fun read if you enjoy Acaster’s comedic style.

×

Entitled by Kate Manne

Book cover: Entitled by Kate Manne. Subtitle: How Male Privilege Hurts Women. Shows a picture of two playing cards; the King of Diamonds sits atop, mostly-covering the Queen of Hearts beneath.I just finished reading Kate Manne‘s Entitled. I can’t remember where I first heard about it or why I opted to buy a copy, but it had been sitting in my to-read pile for a while and so I picked it up last month to read over the festive period.

The book takes a pop-sci dive into research around male entitlement and the near-universal influence of patriarchal ideology. It’s an often bleak and sometimes uncomfortable read: Kate Manne draws a line connecting the most egregious and widely-reported abuses of power by men to much-more-commonplace “everyday” offences, many of which are routinely overlooked or dismissed. The examples she provides are a sad reminder of quite how deeply-embedded into our collective subconscious (regardless of our genders) are our ideas of gender roles and expectations.

It’s feels somewhat chastening to see oneself in some of those examples, whether by my own assumed entitlement or merely by complicity with problematic social norms. We’ve doubtless all done it, at some point or another, though, and we don’t make progress towards a better world by feeling sorry for ourselves. By half way through the book I was looking for action points that never came; instead, the author (eventually) lays out what she’s doing and leaves the reader to make their own decisions.

The vast majority of the book is pretty bleak, and it takes until the final chapter before it reaches anything approximating hope (although the author refrains from classifying it as such), using Manne’s then-imminent parenthood as a vehicle. She finishes by talking about the lessons she hopes to impart to her daughter about how to thrive in this world, which seems less-optimistic than discussing, perhaps, how to improve the world for everybody, but is still the closest thing it delivers to answering “what can we do about this?”.

But I suppose that’s the message in this book: male entitlement is a product of our endemic patriarchy and, try as we might, it’s not going away any time soon. Instead, we should be picking our battles: producing a generation of women and girls who are better-equipped to understand and demand their moral rights and of men and boys who try to work against, rather than exploit, the unfair advantages they’re afforded at the expense of other genders.

That I’d hoped to come to the end of the book with a more feel-good outlook betrays the fact that I’d like there to be some kind of magical quick fix to a problem that I’ve certainly helped perpetuate. There isn’t, and that’s a let down after the book’s uncomfortable ride (not a let down on the part of the book, of course: a let down on the part of the world). The sadness that comes from reading it is magnified by the fact that since its publication in 2020, many parts of the Western world and especially Manne’s own USA have gotten worse, not better, at tackling the issue of male entitlement.

But wishful thinking doesn’t dismantle the patriarchy, and I was pleased to get to the back cover with a slightly sharper focus on the small areas in which I might be able to help fight for a better future. A good read, so long as you can tolerate the discomfort that may come from casting a critical lens over a society that you’ve been part of (arguably it could be even-more-important if you can’t tolerate such a discomfort, but that’s another story).

(In 2025 I’m going to try blogging about the books I read, in addition to whatever else I write about. Expect an eclectic mix of fiction and non-fiction, probably with a few lapses where I forget to write about something until well after I’m deep into what follows it and then forget to say anything about it ever.)

×

Endless SSH Tarpit on Debian

Tarpitting SSH with Endlessh

I had a smug moment when I saw security researcher Rob Ricci and friends’ paper empirically analysing brute-force attacks against SSH “in the wild”.1 It turns out that putting all your SSH servers on “weird” port numbers – which I’ve routinely done for over a decade – remains a pretty-effective way to stop all that unwanted traffic2, whether or not you decide to enhance that with some fail2ban magic.

But then I saw a comment about Endlessh. Endlessh3 acts like an SSH server but then basically reverse-Slow-Loris’s the connecting client, very gradually feeding it an infinitely-long SSH banner and hanging it for… well, maybe 15 seconds or so but possibly up to a week.

Installing an Endlessh tarpit on Debian 12

I was just setting up a new Debian 12 server when I learned about this. I’d already moved the SSH server port away from the default 224, so I figured I’d launch Endlessh on port 22 to slow down and annoy scanners.

Installation wasn’t as easy as I’d hoped considering there’s a package. Here’s what I needed to do:

  1. Move any existing SSH server to a different port, if you haven’t already, e.g. as shown in the footnotes.
  2. Install the package, e.g.: sudo apt update && sudo apt install -y endlessh
  3. Permit Endlessh to run on port 22: sudo setcap 'cap_net_bind_service=+ep' /usr/bin/endlessh
  4. Modify /etc/systemd/system/multi-user.target.wants/endlessh.service in the following ways:
    1. uncomment AmbientCapabilities=CAP_NET_BIND_SERVICE
    2. comment PrivateUsers=true
    3. change InaccessiblePaths=/run /var into InaccessiblePaths=/var
  5. Reload the modified service: sudo systemctl daemon-reload
  6. Configure Endlessh to run on port 22 rather than its default of 2222: echo "Port 22" | sudo tee /etc/endlessh/config
  7. Start Endlessh: sudo service endlessh start

To test if it’s working, connect to your SSH server on port 22 with your client in verbose mode, e.g. ssh -vp22 example.com and look for banner lines full of random garbage appearing at 10 second intervals.

Screenshot showing SSH connection being established to an Endlessh server, which is returning line after line of randomly-generated text as a banner.

It doesn’t provide a significant security, but you get to enjoy the self-satisfied feeling that you’re trolling dozens of opportunistic script kiddies a day.

Footnotes

1 It’s a good paper in general, if that’s your jam.

2 Obviously you gain very little security by moving to an unusual port number, given that you’re already running your servers in “keys-only” (PasswordAuthentication no) configuration mode already, right? Right!? But it’s nice to avoid all the unnecessary logging that wave after wave of brute-force attempts produce.

3 Which I can only assume is pronounced endle-S-S-H, but regardless of how it’s said out loud I appreciate the wordplay of its name.

4 To move your SSH port, you might run something like echo "Port 12345" | sudo tee /etc/ssh/sshd_config.d/unusual-port.conf and restart the service, of course.

×

My Ball

Our beloved-but-slightly-thick dog will sometimes consent to playing fetch, but one of her favourite games to play is My Ball. Which is a bit like fetch, except that she won’t let go of the ball.

It’s not quite the same as tug-of-war, though. She doesn’t want you to pull the toy in a back-and-forth before, most-likely, giving up and letting her win1. Nor is My Ball a solo game: she’s not interested in sitting and simply chewing the ball, like some dogs do.

A champagne-coloured French Bulldog on a black-and-white rug, indoors, stands while chewing a lime green tennis ball.
I’d like to imagine the grunts and snorts she makes at about this moment actually translate to “My ball. Myyyy… ballll. Myyyyy ball! MY BALL! My… BALL!”

No, this is absolutely a participatory game. She’ll sit and whine for your attention to get you to come to another room. Or she’ll bring the toy in question (it doesn’t have to be a ball) and place it gently on your foot to get your attention.

Your role in this game is to want the ball. So long as you’re showing that you want the ball – occasionally reaching down to take it only for her to snatch it away at the last second, verbally asking if you can have it, or just looking enviously in its general direction – you’re playing your part in the game. Your presence and participation is essential, even as your role is entirely ceremonial.

A champagne-coloured French Bulldog in a doorway, on a tiled floor, holds a braided rope; a human hand barely holds the other end.
This might look like a game of tug-of-war, but you’ll note that my grip is just barely two-fingered. She’s not pulling, because she doesn’t need to unless I try to take the toy. This is My Rope, she knows.

Playing it, I find myself reminded of playing with the kids when they were toddlers. The eldest in particular enjoyed spending countless hours playing make-believe games in which the roles were tightly-scripted2. She’d tell me that, say, I was a talking badger or a grumpy dragon or an injured patient but immediately shoot down any effort to role-play my assigned character, telling me that I was “doing it wrong” if I didn’t act in exactly the unspoken way that she imagined my character ought to behave.

But the important thing to her was that I embodied the motivation that she assigned me. That I wanted the rabbits to stop digging too near to my burrow3 or the princess to stay in her cage4 or to lie down in my hospital bed and await the doctor’s eventual arrival5. Sometimes I didn’t need to do much, so long as I showed how I felt in the role I’d been assigned.

A toddler with long blonde hair, wearing a pink cardigan, sits on a tall stool in front of a kitchen sink, holding a long-handled scrubbing brush.
In this game, the chef was “making soup” (in the sink, apparently) and my job was to “want the soup”.

Somebody with much more acting experience and/or a deeper academic comprehension of the performing arts is going to appear in the comments and tell me why this is, probably.

But I guess what I mean to say is that playing with my dog sometimes reminds me of playing with a toddler. Which, just sometimes, I miss.

Footnotes

1 Alternatively, tug-of-war can see the human “win” and then throw the toy, leading to a game of fetch after all.

2 These games were, admittedly, much more-fun than the time she had me re-enact my father’s death with her.

3 “Grr, those pesky rabbits are stopping me sleeping.”

4 “I’ll just contentedly sit on my pile of treasure, I guess?”

5 Playing at being an injured patient was perhaps one of my favourite roles, especially after a night in which the little tyke had woken me a dozen times and yet still had some kind of tiny-human morning-zoomies. On at least one such occasion I’m pretty sure I actually fell asleep while the “doctor” finished her rounds of all the soft toys whose triage apparently put them ahead of me in the pecking order. Similarly, I always loved it when the kids’ games included a “naptime” component.

× × ×

Moving Three Rings’ Servers

Yesterday, I fulfilled the primary Three Rings objective I set for myself when I kicked off my sabbatical twelve weeks ago and migrated the entire application to a new hosting provider (making a stack of related improvements along the way).

Network diagram but with entities having faces and named Chungus, Atul, Summer, Gwen, Alice, Astrid, and Demmy.
If you ignore the smiley faces and names my 10-year-old annotated it with, this diagram’s a reasonably-accurate representation of what each of our three production server clusters look like.

I did some work on this project during my Three Rings-focussed International Volunteer Day last week, but it feels like I’ve been working on it for much longer than that. And it feels like it… because I have been.

Months prior, I was comparing different providers and their relative merits, making sure that our (quirky and specific) needs could be met. Weeks beforehand, I was running a “dry run” every four or five days, streamlining the process of moving the ~450GB1 of live data while minimising downtime. Days before the event felt like the countdown for a rocket launch, with final preparations underway: reducing DNS time-to-lives, ensuring users knew about our downtime window, and generally fitting in a little time to panic.

Terminal screenshot showing a directory listing of a logs directory with several gzipped logfiles with different date-stamped suffixes, and the contents of the logrotate configuration file that produced them.
I made reference on International Volunteer Day to how we needed to configure logrotate. When you’re building architecture for a system as gnarly as Three Rings, there’s about a billion tools that need such careful tweaking2.
The whole operation was amazingly successful. We’d announced an at-risk period of up to six hours and I was anticipating it taking three… but the whole thing was completed within a downtime window of just two and a half hours. And I fully credit all of the preparation time. It turns out that “measure twice, cut once” is a sensible strategy3.

It’s challenging to pull off a “big”, intensive operation like this in an entirely voluntary operation. I’m not saying I couldn’t have done it were I not on sabbatical, but it’d certainly have been harder and riskier.

But then, I also couldn’t have done it without the kickass team of volunteers I’ve surrounded myself with. I guess the real success story here is in the power of a well-aligned team and in volunteer effort.

Footnotes

1 Three Rings‘ user data is represented by a little under 70GB of MariaDB databases plus about 380GB of organisational storage: volunteer photos, files, email attachments, and the like. Certainly not massive by comparison to, say, social media sites, search engines, and larger eCommerce platforms… but large enough that moving it takes a little planning!

2 Okay, a billion tools to configure? That’s an exaggeration. Especially now: since the architectural changes I’ve put in place this week, for example, production app server builds of Three Rings no require a custom-compiled build of Nginx (yes, this really was something we used to need).

3 Which you’d think I’d have realised with my more-successful recent second attempt at secret-cabinet-making.

× ×

Building another secret cabinet

Earlier this year, after our loft conversion work, I built a secret cabinet into the bookshelves I constructed for my new bedroom. My 10-year-old was particularly taken with it1, and so I promised her that when she moved bedroom I’d build one for her.

A bookcase in a child's bedroom, with Christmas decorations visible in the background. Several very old looking books stand conspicuously on the shelf.
Some of these titles perhaps don’t look like they belong, but she doesn’t seem to mind.

My initial order of fake book fronts was damaged in transit but the excellent eBay seller I’d been dealing with immediately sent a comparable replacement. This had left me with a spare-but-damaged set of fake book fronts, but with a little gluing, sawing and filing I was able to turn them into a second usable fake cabinet front.

My 10-year-old’s fake cabinet isn’t quite as sophisticated as mine (no Raspberry Pi Zero, solenoids, or electronic locks) – you just have to know where it is and pull on the correct corner of it to release it – but she still thinks it’s pretty magical2.

The same bookshelf, but now with the older books - actually fake fronts - swung open to reveal an empty cabinet behind.
I’ve no idea what she’ll store in here, and given that she’s on the cusp of becoming a teenager it’s possible I don’t want to know. But at least I know the secret to opening it, should I have to.

A cut-down plank of plyboard stained the right colour, some offcuts of skirting board, a couple of butt hinges, some L-brackets, some bathroom mirror mounting tape, the fake book fronts, and an hour and a half’s work seems totally worth it to give a child the magical experience of a secret compartment in their bedroom. My carpentry’s improved since my one, too: this time I measured twice before cutting3 and it paid-off with a cleaner, straighter finish.

Footnotes

1 She was pretty impressed already at the secret cabinet, but perhaps more-so when she discovered that the fake book fronts I’d used were part of the set of The School for Good and Evil, the apparently-disappointing film version of one of her favourite series’ of books.

2 Which, frankly, it is. I wish I’d had a secret compartment in my bedroom bookshelves when I was her age!

3 Somebody should make a saying about that.

× ×

International Volunteer Day

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

Today is International Volunteer Day. And because I’m in the middle of my (magical) sabbatical, I’ve had no difficulty dedicating what would have been the entire workday to a variety of volunteer activities for the benefit of Three Rings, the nonprofit I founded 22 years ago for the purpose of making volunteer management, and therefore volunteering, easier.

Liveblogging my day

Dan, a white man with a goatee-style beard and long hair tied back, wearing a black t-shirt with an abstract pride rainbow, holds a mug of coffee in one hand and gives a thumbs-up with the other. Behind him, three computer screens show a mixture of code, source control, chat, email, and web browser windows. His desk is cluttered.
Step one in a highly productive day of tech volunteering is, as you might have expected: coffee.

I’m pretty sure that most folks don’t know what my voluntary work at Three Rings involves1, and so I decided I’d celebrate this year’s International Volunteer Day by live-blogging what I got up to in a series of notes throughout the day (1, 2, 3, 4, 5, 6, 7, 8)2.

Maybe, I figured, doing so might provide more of an insight into what a developer/devops role at Three Rings looks like.

Regression-testing a fix

My first task for the day related to a bugfix that we’re looking to deploy. Right now, there’s a problem which sometimes stops the “mail merge” fields in emails sent by Three Rings3. We have a candidate fix, but because it’s proposed as a hotfix (i.e. for deployment directly to production), it requires a more-thorough review process involving more volunteer developers than code which will be made available for beta testing first.

Screenshot showing web application Three Rings viewed on a local development machine, being used to compose an email about International Volunteer Day. A merge field called 'first_name' is included in the email, and it's hand-annotated with the question 'working?'. Alongside, GitHub Desktop shows that we've rolled-back to a revision from two months ago.
My aim with this task was to roll-back to an earlier version of the software, before the bug was first introduced (by fixing something different!), and ensure that the functionality remained the same as it always had been.

It turned out that everything was alright, so I reported back to my fellow reviewers about how I’d tested and what my results had been. Once some more eyes have hit the tests and the new/changed code, that’ll hopefully be ready-to-launch.

Slack screenshot showing a discussion between Dan Q and another volunteer about whether it's reasonable for a volunteer to be able to send another volunteer an email containing private information accessible only to the second volunteer, so long as it's embedded via a merge field and the actual value is never shown to the first volunteer. Ultimately, Dan suggests that we stick to the established behaviour, which turns out after testing to be that volunteers can't send such private information to one another.
Three Rings volunteers primarily communicate via Slack: it helps us to work asynchronously, which supports the fact that our volunteers all have different schedules and preferences for how they plan their volunteering: some spend whole days, some just a few hours now and then. We’re the ultimate “armchair volunteering” opportunity!

Other code reviews

There were also a couple of other code reviews that demanded my attention, so I moved on to those next.

GitHub screenshot showing a suggested change to a pull request. Dan-Q is suggesting that the new sentence 'These roles belong to <%= h @org.name %>.' should not have a full stop at the end, for consistency with other similar headings.
We’re all about collaboration, discussion, learning from one another, and volunteer-empowerment, so my suggestions in this case were non-blocking: I trust my fellow volunteer to either accept my suggestion (if it’s right), reject it (if it’s wrong), or solicit more reviews or bring it to Slack or our fortnightly dev meeting (if it requires discussion).

Preparing new infrastructure

Next week we’re scheduled to do a big migration of server infrastructure to help provide more future growing-room: it’s exciting, but also a little scary4!

Terminal screenshot showing a directory listing of a logs directory with several gzipped logfiles with different date-stamped suffixes, and the contents of the logrotate configuration file that produced them.
For now, though, all I needed to do was to tweak our logrotate and backup configurations in response to testing of our new systems.

Not all of our developer volunteers also wear a “devops” hat, but a few of us do5. It’s quite a satisfying role – devops can feel like tidying and organising, and just as a physical space can feel clean, simple, and functional when it’s carefully and minimalistically laid out, a well-organised cluster of servers humming along in exactly the way they should can be a highly-satisfying thing to be responsible for, too.

Sorting the post

It’s not all techy work, though. And while it’s true that Three Rings has a good group of less-nerdy6 people to handle many of the non-programming tasks that you need to run a voluntary organisation like ours, it’s also true that many of us wear multiple hats and pull our weight in several different roles.

In front of a letterbox, an hand holds an open envelope and a (censored) Danske Bank cheque for £219.
Our time as volunteers may be free, but our servers aren’t, so the larger and richer charities that use our services help contribute to our hosting costs. Most send money digitally, but some use dual-signatory accounts that require they send cheques.

Today, for example, I pulled the recent dead-tree-type post out of our intray and filtered it. Somebody’s got to do these admin tasks, and today I figured it should be me.

Improving our contact form

When people are stuck with Three Rings, or considering using it, or have feature suggestions, or anything else, we encourage them to fill in our contact form. The results of that make their way into our ticketing system where Support Team volunteers help people with whatever it is they need7. They asked if they could have a Slack notification when the form was filled, to grab their attention all the quicker if they were already online, so I obliged and added one.

A filled contact form alongside a Slack message and a resulting ticketing system message.
Adding the Slack notifications meant writing some WordPress PHP code, which feels closer to my “day job” than my Three Rings volunteering!

That quick improvement done, it was time to move on to a task both bigger and more-exciting:

Wrapping up a new feature

I’ve recently been working on an upcoming new feature for Three Rings. Inspired by only occasional user requests, this idea’s been sitting in our (long!) backlog for a while now8: a way to edit the details of volunteers in your organisation in bulk, as though they were in a spreadsheet.

Screenshot showing a web page, 'Three Rings Directory - Edit All': a spreadsheet-like view of multiple volunteers, some of whom have had personal details like First Name, Address, or Telephone changed, resulting in these being highlighted and a prompt appearing to allow the changes to be saved/committed.
The feature’s been almost-complete for weeks now, but I had a few last tweaks to make, based on early feedback and show-and-tell sessions.

I’ve been working on this feature by a series of iterations since the end of October, periodically demonstrating it to other Three Rings volunteers and getting early feedback. In the last round of demonstrations (plus a little user testing, at an in-person Three Rings event) I solicited opinions on how the new feature should be presented, and who it should be made available to9.

So this afternoon I was working on bits of the user interface and, delightfully, got the feature to a point where I only need to update the test instructions and it’ll be ready for a full review and consideration for inclusion in our next milestone release, early next year. Hurrah!

GitHub screenshot showing successful checks passing on a PR.
It’s only a draft PR for now, but at least the initial checks look positive.

Reflecting on my day

I don’t normally get this much Three Rings work done in a day. Even since my sabbatical started, I don’t always get so productive a day10, and when I’m working normally I’d probably only get maybe one or two of these achievements done in a typical week.

So I’m hugely appreciative that my employer encourages staff to take a three-month sabbatical every five years. Because it gives me the opportunity have days like this International Volunteer Day, where I can spend the whole day throwing myself headlong at some valuable volunteering efforts and come out the other side with the satisfaction that I gave my time to make the world a very slightly better place.

If you’re not already volunteering somewhere, I’d highly recommend that you consider it. Volunteering can be purposeful, enriching, and hugely satisfying. Happy International Volunteer Day!

Footnotes

1 In fact, most of the charities who use Three Rings’ services are surprised to discover that we’re a voluntary organisation at all, because we provide the kinds of uptime guarantee, tech support response times, software quality etc. that they might have come to expect from much-richer organisations with a much larger – and paid! – staff. That we’re a voluntary organisation helping voluntary organisations is so unusual that sometimes people have been unsure how to handle us: one time, for example, a helpline charity that was considering making use of us declared us “unsustainable” without a commercial model. At some point in the last decade or two they saw that we’ve outlasted many other services of our type, most of them commercial, and realised: yeah, okay, it turns out we’re in this for the long haul.

2 Gosh: a nine-post day is gonna keep throwing the stats of my recent streak all over the place, isn’t it?

3 My use of italics for Three Rings isn’t arbitrary, but I’ll admit it is confusing. “Three Rings” is the name of our nonprofit. “Three Rings” is the name of the software service we provide. Branding is hard when your company name and product name are the same. And it’s even harder when all of your users insist on abbreviating both to “3R”. 🙄

4 With around 60,000 volunteers depending on Three Rings to coordinate their efforts, the pressure is always on to minimise downtime. I’ve spent many hours over the last few weeks running and re-running through practice runs of the migration strategy before I take the lead on it next week.

5 That said, one of the big things I’ve been pushing for in our new infrastructure is new tools to make it easier for our developers to do “server stuff” like deploying new releases, in an effort to bring us closer to the dream of a continuous integration pipeline. Some day!

6 Or “normal people”, as they might call themselves.

7 The Support Team are a wonderful and hard-working group of volunteers, who aim to reply to every contact within 24 hours, 365 days a year, and  often manage a lot faster than that. They’re at the front-line of what makes Three Rings a brilliant system.

8 While we curate a backlog of user requests and prioritise them based on the optimisation ratio of amount-of-good-done to the amount-of-effort-expected, our developer volunteers enjoy a huge amount of autonomy about what tasks they choose to pick up. It’s not unknown for developers who also volunteer at other organisations (that might be users of Three Rings) to spend a disproportionate amount of time on features that their organisation would benefit from, and that’s fine… so long as the new feature will also benefit at least a large minority of the other organisations that depend on Three Rings. Also, crucially: we try to ensure that new features never inconvenience existing users and the ways in which they work. That’s increasingly challenging in our 22-year-old software tool, but it’s important to us that we’re not like your favourite eCommerce or social networking service that dramatically change their user interface every other year or drop features without warning nor consideration for who might depend upon them.

9 The new feature’s secured such that it works for everybody: if you accessed it as a volunteer with low privileges, you might be able to see virtually nothing about most of the other volunteers and be able to edit only a few details about yourself, for example. But that’d be a pretty-confusing interface, so we concluded that it probably didn’t need to be made available to all volunteers but only those with certain levels of access. We can always revisit later.

10 After all, sometimes I’ve been too busy adding Nex support to CapsulePress, coming up with server naming schemes that don’t suck, teaching myself to like a new flavour or crisps, wearing old clothes, getting thrown off by the combination of timezone moves during daylight savings changes, implementing a 2000-year old algorithm in JavaScript, visiting Spain including PortAventura (and writing more JavaScript for some reason), trying to persuade the children to go to bed, fretting over my sad car, eating quesapizzas, XPath-scraping a friend’s blog, teaching the kids to play Arimaa, enumerating my domain names, playing OpenTTD, not writing a story, considering the twelfth and twentieth amendments, walking the dog in the snow, learning about horse-powered locomotives, teaching my mum to geohash, unlocking graticules, getting caught out by floods, trying to summon a train, geohashing in forests, enjoying gorgeous views, crawling under bridges, getting muddy, boating, in hospital after injuring my arm, or just drinking.

× × × × × × × × ×

Babies and Baubles

For a long time now, every year we’ve encouraged our two children (now 10 and 8 years old) to each select one new bauble for our Christmas tree1. They get to do this at the shop adjoining the place from which we buy the tree, and it’s become a part of our annual Christmas traditions.

A highly-reflective 'soap bubble' glass bauble hangs alongside a glittery gold teardrop-shaped bauble, lit by green and blue fairy lights.
This approach to decoration: ad-hoc, at the whims of growing children, and spread across many years without any common theme or pattern, means that our tree is decorated in a way that might be generously described as eclectic. Or might less-generously be described as malcoordinated!

A cluster of three baubles hangs among pink and white fairy lights: one is a multicoloured assortment of bells, another is a plain white bauble decorated with glittery green and red spots, a third is a transparent plastic sphere containing a colourful children's drawing of a stocking.
But there’s something beautiful about a deliberately-constructed collection of disparate and disconnected parts.

I’m friends with a couple, for example, who’ve made a collection of the corks from the wine bottles from each of their anniversary celebrations, housed together into a strange showcase. There might be little to connect one bottle to the next, and to an outsider a collection of used stoppers might pass as junk, but for them – as for us – the meaning comes as a consequence of the very act of collecting.

A decoration in the form of a bejewelled exotic bird hangs between a traditional bauble with a rippled texture and a hand-painted decoration showing a potted tree.
Each ornament is an untold story. A story of a child wandering around the shelves of a Christmas-themed store, poking fingerprints onto every piece of glass they can find as they weigh up which of the many options available to them is the most special to them this year.

And every year, at about this time, they get to relive their past tastes and fascinations as we pull out the old cardboard box and once again decorate our family’s strangely beautiful but mismatched tree.

It’s pretty great.

Footnotes

1 Sometimes each has made a bauble or similar decoration at their school or nursery, too. “One a year” isn’t a hard rule. But the key thing is, we’ve never since their births bought a set of baubles.

× × ×

99 Days of Blogging

With this post, for the first time ever1, I’ve blogged for 99 consecutive days!2

Calendar showing Sunday 25 August through Sunday 1 December inclusive, with a coloured "spot" on each day with a size corresponding to the number of posts made on that day, broken into a pie chart showing the proportion of different post kinds.
The dots are sized based on the number of posts and broken-down by post kind: articles are blue, notes are green, checkins are orange, reposts are purple, and replies are red3.
I didn’t set out with the aim of getting to a hundred4, as I might well manage tomorrow, but after a while I began to think it a real possibility. In particular, when a few different factors came together:

Previous long streaks have sometimes been aided by pre-writing posts in bulk and then scheduling them to come out one-a-day6. I mostly don’t do that any more: when a post is “ready”, it gets published.

I didn’t want to make a “this is my 100th day of consecutive blogging” on the 100th day. That attaches too much weight to the nice round number. But I wanted to post to acknowledge that I’m going to make it to 100 days of consecutive blogging… so long as I can think of something worth saying tomorrow. I guess we’ll all have to wait and see.

Footnotes

1 Given that I’ve been blogging for over 26 years, that I’m still finding noteworthy blogging “firsts” is pretty cool, I think

2 My previous record “streak” was only 37 days, so there’s quite a leap there.

3 A massive 219 posts are represented over the last 99 days: that’s an average of over 2 a day!

4 This isn’t an attempt at #100DaysToOffload; I already achieved that this year as it does not require consecutive days. But it’s a cool challenge anyway.

5 My site’s backed by WordPress, but the mobile wp-admin isn’t the best and my site’s so-customised that apps like Jetpack mangle my metadata.

6 As you might now, I consider myself to be the primary audience for my blog: everybody else comes second. That’s why I don’t collect any webstats! When I used to collect webstats, I would sometimes pre-write and “schedule” posts, but without them it just feels pointless to do so!

×

Stuck in a Lift

Duration

Podcast Version

This post is also available as a podcast. Listen here, download for later, or subscribe wherever you consume podcasts.

I was a small child the first time I got stuck in an elevator. I was always excited by lifts and the opportunity for button-pushing that they provided1, and so I’d run ahead of my mum to get into a lift, at which point the doors closed behind me. The call button on the outside didn’t work for some reason, and I wasn’t tall enough to reach the “open doors” button on the inside. As a result, I was trapped within the elevator until it was called from another floor.

Dan, aged ~4, stands on a railway station platform alongside his mother, yawning, on a bench. It is overcast and drizzly.
The lift I got stuck in as a child wasn’t here at Liskeard Station in Cornwall2. This photo is just to provide a sense of scale about how small I once was.
That time as a small child is, I think, the only time I’ve been stuck in a lift as a result of my own incapability. But my most-memorable getting-stuck-in-a-lift was without a doubt a result of my own stupidity.

How to brake break a lift

Y’see: it turns out that in some lifts, the emergency brakes are sensitive enough that even a little bit of a bounce can cause them to engage. And once they’re locked-on, the lift won’t move – at all – until the brakes are manually released by an engineer.

As I discovered, way back in March 2004.

Screengrab from the third episode of Russian Doll, showing Alan (Charlie Barnett) and Nadia (Natasha Lyonne) standing in a lift whose red emergency lights have come on.
Contrary to what TV and movies will teach you, it’s actually incredibly difficult to make a lift “drop” down its shaft.

On behalf of Three Rings, I was speaking at the 2004 Nightline Association conference. While there, I’d bumped into my friend Fiona, who was also attending the conference3 The conference was taking place on the upper floor of the Manchester University Students Union building, and as the pair of us got into a lift down to the ground floor, I noticed something strange.

“Woah! This lift is really spongy, isn’t it?” I asked, noticing how much the cabin seemed to bounce and sag as we stepped into it.

“Yeah,” said Fiona, shifting her weight to give it an experimental jiggle.

The elevator started to descend, and as it did so we both gave it another gentle bump, mostly (in my case at least) with an experimental mindset: did it only wobble so much when it was stopped at a floor, or did it do it at all times?

It turns out it did so at all times. Except when it bounced between floors, as we were now, the emergency brakes detected this as a problem and locked on. The lift jerked to an immediate halt. We were stuck.

Touchscreen interface for operating a smart lift, housed in the lobby.
I was reminded of my 2004 capture-by-a-lift in a dream the other night, which in turn was probably inspired by Ruth sharing with me her recent experience of using a “smart” lift she found in Dublin.

We shouted for help from people passing on a nearby floor, and they were able to summon assistance from the lift’s maintenance company. Unfortunately, we were told, because it was a weekend we’d likely have to wait around four hours before anybody could get to us, so we’d have to amuse ourselves in the meantime.

The first thing I learned about Fiona that day

That’s when I made the first of two discoveries that I would make, this day, about Fiona. I learned… that she’s mildly claustrophobic. Not enough to stop her from going into a lift, but enough that when she knows she can’t get out of a lift, it’s likely to cause her a problem. I realised that I should try to find a way to distract her from our situation, so I suggested a game.

“How about I-Spy?” I asked, half-jokingly, knowing that this game could surely not occupy us for long within the confines of a small metal box.

“Sure,” she agreed, “You go first.”

Three-storey building on a city street.
The Manchester University Student’s Union building. Image courtesy Peter McDermott, used under a CC-By-SA license.

“I spy with my little eye… something beginning with… N!” I said. If we were going to be stuck here playing I-Spy for several hours, I might as well pick something deviously tricky. Embedded into the corners of the floor were four recessed hexagonal nuts: my word was nut. That’d keep her occupied for a while.

I forget what she guessed and when, but she eventually guessed correctly. It probably took less than 5 minutes. Now it was her turn.

The second thing I learned about Fiona that day

Fiona thought for a little while, looking around our tiny prison for inspiration. Eventually, she’d found something:

“I spy with my little eye,” she said. Then, after a pause: “Something beginning with… S.”

“Screw?” I asked, assuming immediately that she’d have chosen something as devious as I’d thought mine was, and noticing that the button panel was secured with a quartet of recessed flat-head screws. Nope, Fiona indicated.

“Shoes? Oh! Soles?” I suggested, pointing to the bottoms of my shoes, which were visible as I sat on the floor of the lift. Nope.

“Shirt? Socks?” I glanced at myself. I wasn’t sure there was much inside the lift that wasn’t me or Fiona, so it seemed likely that the thing I was looking for was on, or part of, one of us.

“Step?” I gambled, indicating the metal strip that ran underneath the closed doors. No luck.

“Umm… shaft? Can you see part of the lift shaft somehow?” A smirk and an eye roll. I was getting further from the right answer.

Finger pressing a lift button.
It turns out there’s not much to I-Spy in a stopped elevator. “Six? Seven? No… wait… there aren’t that many floors in this building…”

“Ssss….sliding doors?” “Slit?” “Slot?” Still nothing.

This continued for… three… hours4. Fiona sat, self-satisfied, smugly enjoying my increasing frustration right up until the point at which the lift engineer arrived and began levering open the doors on one of the two floors we were between to allow us to wriggle our way out. I must’ve inspected every square centimetre of that tiny space, of myself, and of my gaming companion. Clearly I was alongside the world grandmaster of I-Spy and hadn’t even known it.

“Okay, I give up,” I said, at last. “What the hell was it?”

Soon, I would make the second of the two discoveries I would make about Fiona that day. That she’s quite profoundly dyslexic.

“Circle,” she said, pointing at the lit ring around the alarm button, which we’d pressed some hours before.

Dan, touching his temples, a pained look on his face.
I don’t think it’s possible for a person to spontaneously explode. Because if it were, I’d have done so.

I’d like to think that when Fiona got stuck in a lift a second time that same Spring, it was karma.

Footnotes

1 My obsession with button-pushing as a child also meant that it was hard to snap a photo of me, because I always wanted to be the one to press the shutter button. I’ve written about this previously, if you’d like to see examples of a photos I took as a toddler.

2 The photo is, specifically, Platform 3 of Liskeard Station, which is distinctly separate from the other two platforms, requiring that you leave the main station and cross the road. This is a quirky consequence of the way this section of the Liskeard to Looe branch line was constructed, which necessitated entering Liskeard at right angles to the rest of the station.

3 If I remember rightly, I first met Fiona on a bulletin board when she volunteered to help test Three Rings. She later visited Aberystwyth where she and Kit – who was also helping with the project back in those days – fell in love. It was very sweet.

4 I’d love to say that the three hours flew by, but they didn’t. But it was still infinitely preferable to being stuck in there alone. And, in fact, there are plenty of people for whom I’d have rather been stuck alone than stuck with.

× × × × × ×

Horse-Powered Locomotives

You’re probably familiar with the story of George and Robert Stephenson’s Rocket, a pioneering steam locomotive built in 1829.

If you know anything, it’s that Rocket won a competition and set the stage for a revolution in railways lasting for a century and a half that followed. It’s a cool story, but there’s so much more to it that I only learned this week, including the bonkers story of 19th-century horse-powered locomotives.

The Rainhill Trials

Collage of contemporary illustrations of the Perseverance, Sans Pareil, Novelty, and Rocket.
Ten teams submitted applications to enter the Rainhill Trials, but only five actually took part. Four of these were the steam locomotives illustrated above.

Over the course of the 1820s, the world’s first inter-city railway line – the Liverpool & Manchester Railway – was constructed. It wasn’t initially anticipated that the new railway would use steam locomotives at all: the technology was in its infancy, and the experience of the Stockton & Darlington railway, over on the other side of the Pennines, shows why.

The Stockton & Darlington railway was opened five years before the new Liverpool & Manchester Railway, and pulled its trains using a mixture of steam locomotives and horses1. The early steam locomotives they used turned out to be pretty disastrous. Early ones frequently broke their cast-iron wheels so frequently; some were too heavy for the lines and needed reconstruction to spread their weight; others had their boilers explode (probably after safety valves failed to relieve the steam pressure that builds up after bringing the vehicle to a halt); all got tied-up in arguments about their cost-efficiency relative to horses.

Book scan, reading "When it is considered how much inconvenience must have resulted from the temporary withdrawal of one of these engines from active service, it is not, perhaps, surprising to find among the early accounts of the Quaker Company, under the head of Contingent Expenses, 'an item of 16s. 9d.' for men's allowance in ale to stimulate them to greater exertion, while repairing the engine."
Nowadays, a train can be cancelled and a paying customer might barely get a half-hearted apology and a spot on a crowded rail replacement bus. But back in 1826 even the crew of a broken-down train might be offered a copious allowance of beer to keep them motivated. Scan from page 119 of The North Eastern Railway; its rise and development, by William Weaver Tomlinson.

Nearby, at Hetton colliery – the first railway ever to be designed to never require animal power – the Hetton Coal Company had become so-dissatisfied with the reliability and performance of their steam locomotives – especially on the inclines – that they’d had the entire motive system. They’d installed a cable railway – a static steam engine pulled the mine carts up the hill, rather than locomotives.

This kind of thing was happening all over the place, and the Liverpool and Manchester Railway Company were understandably cautious about hitching their wagon to the promise of steam locomotives on their new railway. Furthermore, they were concerned about the negative publicity associated with introducing to populated areas these unpopular smoke-belching engines.

But they were willing to be proven wrong, especially after George Stephenson pointed out that this new, long, railway could find itself completely crippled by a single breakdown were it to adopt a cable system. So: they organised a competition, the Rainhill Trials, to allow locomotive engineers the chance to prove their engines were up to the challenge.

Advertisement for "Rapid, Safe, and Cheap Travelling by the Elegant New Railway Coach" of the Stockton & Darlington Railway, opening "Monday the 16th day of October, 1826", showing a woodcut picture of a rail coach being pulled by a galloping horse.
When the Stockton & Darlington line began serving passengers in 1826, their advertisements only ever showed passenger coaches being pulled by horses, never steam locomotives.

The challenge was this: from a cold start, each locomotive had to haul three times its own weight (including their supply of fuel and water), a mile and three-quarters (the first and last eighth of a mile of which were for acceleration and deceleration, but the rest of which must maintain a speed of at least 10mph), ten times, then stop for a break before doing it all again.

Four steam locomotives took part in the competition that week. Perseverance was damaged in-transit on the way to the competition and was only able to take part on the last day (and then only achieving a top speed of 6mph), but apparently its use of roller bearing axles was pioneering. The very traditionally-designed Sans Pareil was over the competition’s weight limit, burned-inefficiently (thanks perhaps to an overenthusiastic blastpipe that vented unburned coke right out of the funnel!), and broke down when one of its cylinders cracked2. Lightweight Novelty – built in a hurry probably out of a fire engine’s parts – was a crowd favourite with its integrated tender and high top speed, but kept breaking down in ways that could not be repaired on-site. And finally, of course, there was Rocket, which showcased a combination of clever innovations already used in steam engines and locomotives elsewhere to wow the judges and take home the prize.

But there was a fifth competitor in the Rainhill Trials, and it was very different from the other four.

Cycloped

When you hear the words horse-powered locomotive, you probably think of a horse-drawn train. But that’s not a locomotive: a locomotive is a vehicle that, by definition, propels itself3. Which means that a horse-powered locomotive needs to carry the horse that provides its power…

Thomas Shaw Brandreth's "Cycloped", a locomotive powered by a treadmill on which a horse walks.
If this isn’t the most-zany railway vehicle you’ve ever seen, please share what beats it.

…which is exactly what Cycloped did. A horse runs on a treadmill, which turns the wheels of a vehicle. The vehicle (with the horse on it) move. Tada!4

You might look at that design and, not-unreasonably, decide that it must be less-efficient than just having the horse pull the damn vehicle in the first place. But that isn’t necessarily the case. Consider the bicycle which can transport itself and a human both faster and using less-energy than the human would achieve by walking. Or look at wind turbine powered vehicles like Blackbird, which was capable of driving under wind power alone at three times the speed of a tailwind and twice the speed of a headwind. It is mechanically-possible to improve the speed and efficiency of a machine despite adding mass, so long as your force multipliers (e.g. gearing) is done right.

Blackbird traveling downwind faster than the wind, as shown by the streamers on the vehicle and the flag on the ground, pointing in opposite directions.
I’ve long loved this 2010 photo of Blackbird, simultaneously showing a flag (blowing left, with the wind) and a streamer (blowing right, as a result of the wind-powered vehicle’s speed) demonstrating that it is travelling against the wind, but significantly faster than the wind.

Cycloped didn’t work very well. It was slower than the steam locomotives and at some point the horse fell through the floor of the treadmill. But as I’ve argued above, the principle was sound, and – in this early era of the steam locomotive, with all their faults – a handful of other horse-powered locomotives would be built over the coming decades.

Over in the USA, the South Carolina Canal and Railroad Company successfully operated a passenger service using the Flying Dutchman, a horse-powered locomotive with twelve seats for passengers. Capable of travelling at 12mph, this demonstrated efficiency multiplication over having the same horse pull the vehicle (which would either require fewer passengers or a dramatically reduced speed).

A railway carriage containing 12 passengers, two operators, and a horse, the latter of which powers the vehicle.
This strange contraption was eventually replaced with a steam train, under the understanding that improvements in steam locomotive technology would continue to develop faster than advancements in techniques for the selective breeding of horses.

As late as the early 1850s, people were still considering this strange approach. The 1851 Great Exhibition at the then brand-new Crystal Palace featured Impulsoria, which represents probably the pinnacle of this particular technological dead-end.

Capable of speeds up to 20mph, it could go toe-to-toe with many contemporary steam locomotives, and it featured a gearbox to allow the speed and even direction of travel to be controlled by the driver without having to adjust the walking speed of the two to four horses that provided the motive force.

A locomotive featuring four horses climbing an inclined conveyor belt under the supervision of two humans.
The reins now arriving on platform one is the Mane Line service to Carlisle. Mind the gallop. Stand clear of the hackamore.

Personally, I’d love to have a go on something like the Flying Dutchman: riding a horse-powered vehicle with the horse is just such a crazy idea, and a road-capable variant could make for a much better city tour vehicle than those 10-person bike things, especially if you’re touring a city with a particularly equestrian history.

Footnotes

1 From 1828 the Stockton & Darlington railway used horse power only to pull their empty coal trucks back uphill to the mines, letting gravity do the work of bringing the full carts back down again. But how to get the horses back down again? The solution was the dandy wagon, a special carriage that a horse rides in at the back of a train of coal trucks. It’s worth looking at a picture of one, they’re brilliant!

2 Sans Pareil’s cylinder breakdown was a bit of a spicy issue at the time because its cylinders had been manufactured at the workshop of their rival George Stephenson, and turned out to have defects.

3 You can argue in the comments whether a horse itself is a kind of locomotive. Also – and this is the really important question – whether or not Fred Flintstone’s car, which is propelled by his feed, is a kind locomotive or not.

4 Entering Cycloped into a locomotive competition that expected, but didn’t explicitly state, that entrants had to be a steam-powered locomotive, sounds like exactly the kind of creative circumventing of the rules that we all loved Babe (1995) for. Somebody should make a film about Cycloped.

× × × × × × ×