from/prod
← All companies

THE COMPANY INDEX TRACKED BLOG

Huon Wilson

Ideas, decisions, and lessons from the team.

huonw.github.io (opens on the source site)
25Posts tracked
6 months agoLatest publication
0.6Posts / month over the last 12 months

Latest writing

20 of 25 posts

Gell-Mann AImnesia (opens on the source site)

Any time I use an AI tool for something I’m deeply familiar with, I find a continual stream of mistakes and inconsistencies. When I use it on a topic I don’t know… everything sounds plausible and I don’t find mistakes. The difference worries me, and sounds a lot like the Gell-Mann Amnesia effect. AI can write confidently on any topic, with good presentation, just like newspaper articles. I find this easy to see through for areas in which I am the one who is competent, but notice myself nodding along in areas where I have less expertise. This contrast is stark: do I really think AI is…

Read at the source

Write broken commits for better review (opens on the source site)

I spend a lot of time reviewing code, and I think it’d be easier if I saw more tastefully broken commits. Commits construct a story about a change: “first this happened, then that, that another thing” is a good narrative; “first everything happened, the end”… not so much. Sometimes, telling that story is impossible without having a commit that breaks tests or doesn’t compile! The principle that usually drives me to commit broken code is making mechanical changes obviously mechanical and mechanically obvious: reformatting, renaming a function or file, re-indenting, … are not “real” changes…

Read at the source

Why don't multi-column indices help queries on the second column? (opens on the source site)

SQL databases support multi-column indices, where a single index can incorporate data from multiple columns. These are powerful, but the order of the columns matters, with differences observable in practice: there can be orders of magnitude between two similar & simple queries, depending on which uses a prefix of the index columns. Why does this limitation exist? Can we have a mental model for the indices that explains the behaviour? Yes, we can: thinking about indices as a sorted table with multiple columns provides that intuition: For a query involving the first columns, successive lookups…

Read at the source

Staying engaged with AI plans: give inline feedback (opens on the source site)

When I use an AI coding agent to make a plan, I make a habit of opening that plan in my editor and then leaving inline comments with questions, requests and corrections directly in the file. The agent seems to be happy enough to work with these, and I find it gives better results than reading the plan in the agent and using chat to give feedback. By being a habit, it keeps me honest and stops me from slipping into lazy bad habits: waving a plan through to implementation without engaging or proper consideration.0 Plus, providing feedback this way is low-overhead and convenient: my editor is…

Read at the source

magit-insert-worktrees improves status buffers (opens on the source site)

The Magit package for Emacs is my Git UI of choice, and git worktrees are very convenient. They mesh up particularly well by adding the built-in magit-insert-worktrees to magit-status-sections-hook. With this, the magit status buffer shows a summary of the branch/HEAD/path of all worktrees, and allow jumping between them in a flash. 1 2 ;; Show all worktrees at the end of the status buffer (if more than one) (add-hook 'magit-status-sections-hook #'magit-insert-worktrees t) A magit status buffer with all the usual features, plus the new ‘Worktrees’ section at the end: the outlined row with an…

Read at the source

TypeScript strictness is non-monotonic: strict-null-checks and no-implicit-any interact (opens on the source site)

The TypeScript compiler options strictNullChecks and noImplicitAny interact in a strange way: enabling just strictNullChecks leads to type errors that disappear after enabling noImplicitAny too, meaning getting stricter has fewer errors! This is a low-consequence curiosity, but I did trip over it in the real world, while updating some modules at work to be stricter. The context TypeScript is a powerful tool for taming a JavaScript codebase, but getting the most assurance requires using it in “strict” mode. Adopting TypeScript in an existing JavaScript codebase can be done incrementally by…

Read at the source

Context privateering: debugging custom instructions like a pirate (opens on the source site)

I occasionally add context instructions to an AI tool, but then am not sure whether those changes were picked up by the tool. The fun way to debug this is to add “Always speak like a pirate” to the instructions. This works in all tools. Context engineering! Context I use LLM tools like Claude Code. These come with the ability to customise the context fed to the model with files like ~/.claude/CLAUDE.md or /CLAUDE.md, which can be used for personal and/or project-specific guidelines and tips. When editing them, sometimes I find the tool is opaque, and it’s not clear if I’ve configured things…

Read at the source

Is that a deprecation? Or is it just removed? (opens on the source site)

I’ve noticed different people seem to use the word “deprecating” to mean two different things, when it comes to code and/or features: either removing entirely, or discouraging its use. I think it’s useful to have specific labels for both of these of concepts, so that communication is clearer. When you want to discourage new users of some existing code/feature, and… existing users continue working for now, call it deprecating existing users stop working immediately, call it removing (or deleting, renaming, or… something else, as appropriate) Rephrased: describing the removal of X as “X is…

Read at the source

Convenient 'Copy as cURL': explicit, executable, editable request replays (opens on the source site)

The network tab of a browser’s developer tools shows a list of requests. Sometimes there’s a problem with one of those requests! Maybe the server is crashing and returning a 500 error, or maybe there’s an unexpected 403 permission error. The dev tools UIs provide one-click “Copy as cURL” functionality to conveniently extract an executable ‘replay’ of the request, and it can be easily edited. This makes communicating and debugging issues with HTTP requests much easier. Many a time I have had another software engineer ask me “I did $vague_description and it failed”, requiring a few rounds of…

Read at the source

Communicating bugs: use a single standalone shell script (opens on the source site)

Hitting a bug is no fun: maybe it interferes with your work or play, or maybe it means you have to dive down a debugging rabbit hole. Remotely debugging a bug someone else has found is even less fun… I’ve settled on using a shell script for sharing executable self-contained reproducers for issues I find in software libraries and developer tools, to get help faster. Sometimes, when I’ve found an issue, telling someone how to see it for themselves—how to reproduce it—is trivial: “go to this documentation link https://... and see the typo: miispeled”. However, it’s usually harder. Reproducing a…

Read at the source

Take a break: Rust match has fallthrough (opens on the source site)

Rust’s match statement can do a lot of things, even C-style fallthough to the next branch, despite having no real support for it. It turns out to be a “shallow” feature, where the C to Rust translation is easily done, without needing to understand the code itself. The hardest part is coming to terms with writing it, and then convincing someone else to let you land it! Here’s what the tail handling of the MurmurHash3 hash function could look like, in Rust, if you have enough courage0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 'outer: { 'case1: { 'case2: { 'case3: { match len & 3 { 3 =>…

Read at the source

Newtons are a unit of mileage (opens on the source site)

The conventional units for expressing the mileage of an electric vehicle, like Wh/km (“watt-hours per kilometer”), are dimensionally equivalent to force, N (“newtons”). It seems this has a useful physical interpretation, and we can do some rough predictive calculations by estimating the drag and rolling resistance forces that align to real-world observed efficiencies. We recently got a battery electric vehicle. We took a road trip which both left me with new dials and sensors to play with, and involved many hours of boring highway driving… the perfect time for some dimensional analysis!0…

Read at the source

Prefer tee -a, not >>, in CI (opens on the source site)

Shell scripts sometimes have to append data to a file. Redirecting output with >> is the conventional way and works fine, but using tee -a instead is a usually better default, especially in continuous integration. It’s just as easy and gives automatic introspection: the same value is printed to stdout and so appears in normal logs too. 1 2 3 4 # conventional approach (worse!): echo "some_variable=some_value" >> "$GITHUB_ENV" # preferable approach (better!): echo "some_variable=some_value" | tee -a "$GITHUB_ENV" This occurs for me most often in continuous integration (CI), and especially with…

Read at the source

Async hazard: mmap is secretly blocking IO (opens on the source site)

Memory mapping a file for reading sounds nice: turn inconvenient read calls and manual buffering into just simple indexing of a memory… but it does blocking IO under the hood, turn a &[u8] byte arrays into an async hazard and making “concurrent” async code actually run sequentially! Code affected likely runs slower, underutilises machine resources, and has undesirable latency spikes. I’ve done some experiments in Rust that show exactly what this means, but I think this applies to any system that doesn’t have special handling of memory-mapped IO (including Python, and manual non-blocking IO in…

Read at the source

GitHub tip-hub: habitual permalinks (opens on the source site)

GitHub offers permalinks to versions of files and lines, within a repository. They’re easy to create (y keyboard shortcut) and have some nifty affordances like displaying a preview, plus they don’t become invalid as code changes. Use them! The permalinks use the commit hash of a particular version of the file, and thus the contents never changes, because they’re content-addressed and permanent0. This is true even as the code evolves: a permalink to a particular line will always be what you intended, whether future versions add or remove code around it, or even move or delete the file…

Read at the source

10 > 64, in QR codes (opens on the source site)

Encoding data in decimal requires many more characters than the same data encoded in base64—06513249 vs YWJj—but using decimal is better when stored in a QR code. The magic of QR modes means all those extra digits are stored efficiently, almost as though there was no encoding at all. Decimal encoding makes for QR codes that store more data, or are easier to scan. In this post, we’ll see: how using a decimal encoding (slightly) reduces the density of a QR code containing a URL, in practice; why QR code modes make this work: decimal data is all URL-safe and stores in a QR code Numeric mode…

Read at the source

Mechanical sympathy for QR codes: making NSW check-in better (opens on the source site)

Governments here in Australia have been telling us to keep distance from each other. Surprisingly, the same government has simultaneously put out posters that required people to get close, unnecessarily. They contain QR codes for contact-tracing check-ins that are small and dense, meaning they’re hard to scan. How could they be better? Here’s how: Three pages placed horizontally. They all contain a 'we're covid safe' logo, text like 'please check in before entering our premises.' and a QR code. The left-most one labelled 'original' in red has a very small QR and dense code; the centre one…

Read at the source

QR error correction helps and hinders scanning (opens on the source site)

Error correction sounds good. It means fewer errors, right? When it comes to QR codes, that’ll mean easier scanning for people, surely? It seems like that’s not the whole story. I wondered about this, and couldn’t find an answer, so I did some exploration, and found there’s two factors in tension: the error correction on one hand, and the resulting data density on the other: For fixed data, like a particular URL, it’s easier to read a QR code with lower error correction, but only when there’s minimal damage to the code (like reflections and dirt). Error correction works as advertised when…

Read at the source

The joy of cooking (an app) (opens on the source site)

Taking shortcuts? Leaving edge-cases unconsidered and unhandled? Is this engineering?! My approach to programming and software engineering has been shaped by years of building open source compilers and libraries, where those edge cases matter, reliability is crucial and flexibility is important. It’s been a breath of fresh air to take a step back and stop thinking about every detail, and instead write code that works for a specific set of people: me and my wife. Early in 2020 (while fires raged, in the before-times), I read Robin Sloan’s An app can be a home-cooked meal and the idea of code…

Read at the source

Git worktrees and pyenv: developing Python libraries faster (opens on the source site)

It’s glorious to work on one task at a time, to be able to take it from start to finish completely, and then move onto the next one. Sounds great, but reality is messier than that and context switches are common. Doing so can be annoying and inefficient, but not switching means tasks and colleagues are delayed. I combine git worktrees and pyenv (and plugins) to reduce the overhead of a context switch and keep development and collaboration as smooth as possible when working on a Python library. Reducing the pain of a context switch allows me to work on many tasks concurrently: usually one or…

Read at the source

Privacy choices

Reading never requires analytics. These choices last 90 days on this browser.

Essential sign-in and security storage always stays on. Read the privacy notice.