Weeknotes


June 29-July 5, 2026

Back at home this week, I spent a lot of time with my new Framework Desktop. Over the course of my PhD, I’ve been slowly but surely transitioning from coffee-shop worker to a seated homebody.1

Rheo[26w27-rheo]

I cut a new release of Rheo this week, 0.4.0. This version both upgrades Rheo to Typst 0.15.0 as its Typst compilation engine, and also uses the new bundle compilation target as the primary mechanism for compiling Rheo spines. The former engine upgrade means that Rheo 0.4.0 compiles Typst math syntax to MathML in HTML, and the latter spine implementation detail means that Rheo now supports Typst-native labels for relative linking in projects.

I also massaged out an early design decision that had been turning into something of a leaky abstraction, namely a global merge attribute on all implementations of FormatPlugin. My original thinking was that, by toggling merge as true/false, a user could determine whether they wanted a spine to ‘reticulate’ (compile) into one document (as a single PDF, say), or into N documents (where N is the number of vertebrae in the spine). Now that I’ve been using Rheo for all my writing for a few months, I’ve decided that this optionality stuffs more complexity into Rheo’s API than it’s worth. The formats we currently care about—PDF, HTML, and EPUB—have a baked-in notion of whether they should produce 1 or N files ("pdf" = 1, "html" = N, "epub" = 1. EPUB is actually something of a hybrid, as we produce N XHTML files, but then package them as 1 file.)

Besides not really being useful to me in practice, the global merge attributed added complexity to the lifecycle of FormatPlugin implementations. When merge was true, compile would only be called once, as all of the spine vertebrae would be assembled into a single virtual file that would then be passed off to the Typst compiler. When merge was false, however, compile was called once per vertebra, which led to poor performance, as Rheo would essentially have to run a typst compile command for every vertebra independently. Because Typst 0.15.0 makes it possible to produce multiple (N) output files from a single typst compile invocation, in 0.4.0, Rheo’s compile function is only ever called once, regardless of whether it produces 1 or N files. The merge attribute doesn’t exist any longer, although it could be added back as a format-specific option in the pdf crate if there is a need.

Because I now have  10 sites that I maintain with Rheo, I also added a rheo migrate command. This makes a best-effort attempt at modifying a Rheo project so that its syntax and configuration matches the most recent version of Rheo. In the simplest case, this just requires setting the version in rheo.toml to the latest, i.e. 0.4.0 at time of writing. But because the relative linking syntax has also changed, this command will also attempt to rewrite links from the old syntax (#link("./index.typ")[Home]) to the new one (#link(<index>)[Home]).

I also added documentation for the slides plugin (one of the important use cases of Rheo for me that has been difficult to manage in Typst natively) and consolidated the configuration around Atom feed support.

I’m quite happy with Rheo’s shape now. I use it daily (for all my writing, documentation, and slides), and it seems that there are at least a couple of other people using it. It’s getting close to 200 stars on GitHub, but I only know of 2-3 others who have actively reported using it. This could, of course, simply be because many others have used it and found nothing to complain about—but I somehow doubt this. Crates.io does show around 300 downloads, and I don’t think that includes cargo binstall (?), which is the recommended way of installing Rheo on the docs and README, so that’s promising.

Typst Limited Forms Application[26w27-typst]

I heard back this morning (Monday 6th July) that I wasn’t selected to implement the limited project this summer adding support for forms at Typst. I thought the interview (on Wednesday 1st July) had gone relatively well, as I had identified a number of issues with my take-home assignment in advance, and thought that I had demonstrated a reasonable ability to refine and improve the design in the 1-hour interview. In any case, it was nice to receive some written feedback about why I wasn’t selected:

The section of your take home about type mappings in the API was well thought-out and matches Typst design spirit. Groups and fieldsets were one of the focal areas you chose for the take home and we zeroed in on them during our interview. We felt like at the end of the interview, we still did not achieve clarity about the rationale, use, or implementation of groups and did not manage to sufficiently differentiate them from field sets. During our interview, we also noticed that having the editor open at times did more harm than good as it took focus away from the conversation. Nevertheless, both your presentation of Rheo and the take home were approachable and showed that you did your research.

All in all, this seems a fair assessment, and suggests to me that the main reason I wasn’t selected is because another candidate was a better fit / performed more impressively in the take-home and interview. There were some unresolved issues with groups/fieldsets from the interview, and though I personally felt that I made good progress on smoothing them out over the course of the interview, it’s possible that there are deeper contours of the PDF/HTML spec that I hadn’t considered that render my design fundamentally weak or otherwise inappropriate. The feedback about having my editor open is interesting, too. I personally felt that we were able to specify and resolve several issues precisely because we were looking at concrete examples. But it’s useful to know that this was most likely a solipsistic experience, rather than a feeling shared by my interviewers, and I will certainly keep this comment in mind during future interviews / pair-programming sessions.

I’ll of course be curious to track the implementation of forms as it does happen over the course of this summer; and to learn more about Typst from the design that bested my proposal! Though I’m naturally a little disappointed that I didn’t get this gig, it does free me up a little to focus on my dissertation and other projects that are beginning to get into flight this summer (see Section 10.0.4 below, for example). So the disappointment at least hit this morning with a slight touch of relief.

LIMINAL[26w27-liminal]

I spent a good portion of Thursday and some 10 hours on Friday putting the finishing touches to this frontend platform, about which I wrote a couple of weeks ago. The platform will hopefully be released publicly soon, and despite my deepening alienation from frontend development, I’m quite proud of the platform from both a design and investigative perspective. I wasn’t responsible for any of the investigative work, really; but I do think it documents important aspects of the changing nature of migrant pushbacks on the Mediterranean. Besides a few tweaks and touches in design review, I don’t expect to be sinking much more time into development of this platform, which is also something of a relief. At this stage, it’s been more than a year since I decided to get involved with the project. As is often the case with investigative platforms of this nature, we spent a lot more time refining the design and waiting on collaborators than anticipated, and so the project has been drawn out beyond its original context.

Konrad[26w27-konrad]

I was inspired to start a new project this week building an agential harness from scratch. This is partly a pedagogical exercise so that I can better understand the mechanics of tools like Claude Code, which is now an essential component of my coding workflow, prompted by reading about Anil Madhavapeddy’s own experiments with bootstrapping an agential harness in OCaml. But I also think building agential harnesses that use local models effectively (as opposed to models hosted by frontier labs or compatible APIs) might be a space in which genuine research/hacking needs to be done.

After a bit of jockeying with Kagi Assistant (my LLM research platform of choice), I settled on the name konrad; following the naming inspiration of Anthropic’s ‘claude’, but with reference to the first name of a different computing luminary known for his autodidactical elan. I’m developing the codebase on tangled:

The idea is first to build an implementation in Rust, as this is the language with which I’m most familiar, and which seems most appropriate to the task at hand given that it will need to interface with relatively low-level code to run local models as close to the metal as possible. If that goes well, then I have in mind to see how successively I might develop alternative implementations in either/both OxCaml and Lean, two languages about which I’d like to learn more, from a language-independent spec that I’ll try to build alongside the initial Rust impl. This experiment is spirited by the idea that, given how well LLMs can now produce code, there might be newfound gravity in a software’s specification and test suite independent of any canonical implementation.

Dissertation[26w27-diss]

Dissertation work slipped a little under the radar this week. But I did wake up in the middle of one night and finish an essay or two that I’ve been meaning to digest. And I took Jensen Suther’s True Materialism up again. I should focus more here this coming week.

et alia[26w27-etal]

I discovered a glorious new climb on my road bike one evening:

The route out wasn’t particularly inspiring in the 5-6PM traffic, but the salita over the lake was well worth the moto scoppio. Next time I’ll consider taking the train out the first 10km, as it would make the ride both more pleasant and easier to fit into the day.

Those who follow professional cycling will know that the Tour de France started this weekend. The best way to watch cycling is to be cycling yourself on an indoor trainer: and so I’ve set up my Zwift in the cellar (where I keep my real bikes) and augmented it with an extra screen so that I can run both the Tour and Zwift concurrently:

When it was set up in my previous residence’s turreted office, this Zwift station was aptly dubbed the ‘Power Tower’. I like this real rhyme much better than the ‘pain cave’ (common and colloquial nickname for an indoor cycling setup these days), even if the latter is inarguably the more appropriate to my new setup’s elevation and aesthetic. So the Power Tower it remains! I will be pushing watts (paltry compared to the pros) on this thing for many hours over the next three weeks while I watch Tadej Pogacar make winning races look like child’s play, despite all the world’s other best riders being in the bunch.

  1. 1 This transition has been helped along by the fact that I now drink coffee almost exclusively at home in search of quality. Perhaps I’ll update the desiring world on the particulars of my coffee-making setup in a post on my main blog sometime soon.