<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>fifthrevision</title><description>Chong Han is a software designer and maker based in San Francisco, California.
</description><link>https://fifthrevision.com/</link><item><title>Why I built dtg</title><link>https://fifthrevision.com/writing/2026/why-i-built-dtg.html</link><guid isPermaLink="true">https://fifthrevision.com/writing/2026/why-i-built-dtg.html</guid><description>A brief history of how I picked colors</description><pubDate>Wed, 28 Oct 2026 03:59:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;lead-in&quot;&gt;I don’t remember when,&lt;/span&gt; but it got to a point where the colors I picked for the design systems became preposterously difficult to maintain. Perhaps it started around the time when I started building them by meticulously layering semi-opaque rectangles in a drawing tool like Figma.&lt;/p&gt;
&lt;p&gt;There’s an art and a science to building pleasing color systems. To achieve the desired uniformity I wanted, I found it easiest to build the scales algorithmically, that is, defining all the constituent parts and then deriving each step from them. The colors, whether sampled from Figma or a dedicated tool that I built, then get put into the variables panel in Figma. This process works for as long as there are no changes to them, at which point it becomes deliriously difficult to maintain.&lt;/p&gt;
&lt;p&gt;I remember two specific instances that led me down the path to dtg. In the first, I created this elaborate system of rectangles of different opacity in Figma and sampled every single swatch into the variables panel. Once, I decided that the background color needed to go darker. I had to go back into the project, change the color of the background frame, and then manually update all 54 colors inside the design system. This was but one of many.&lt;/p&gt;
&lt;figure class=&quot;image &quot;&gt;&lt;a class=&quot;zoom&quot; href=&quot;/assets/images/posts/26-10-27/figma-color-palettes@2x.png&quot; target=&quot;_blank&quot;&gt;&lt;img class src=&quot;/assets/images/posts/26-10-27/figma-color-palettes.png&quot; srcset=&quot;/assets/images/posts/26-10-27/figma-color-palettes@2x.png 2x&quot; alt=&quot;A Figma screenshot of rectangles used to generate color palettes&quot;&gt;&lt;/a&gt;&lt;figcaption&gt;&lt;p&gt;I used to maintain elaborate structures of rectangles so I can tweak colors and re-sample them.&lt;/p&gt;
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;a href=&quot;https://archives.fifthrevision.com/color-generator/index.html&quot;&gt;dedicated web tool&lt;/a&gt; simplified the first half of that process. The color palettes could now be computed, but every tweak still meant updating significant swaths of the palette by hand. And changes are inevitable. After all, colors are contextual to how they are used; it is nigh impossible to get it right the first time round.&lt;/p&gt;
&lt;p&gt;I remember vividly the moment I took a detour from an active project to finish the first version of dtg. I was trying to visualize a half a percent (!) shift among a set of background colors and I was deliberating the line where a separation becomes a distinction. Because the colors were built in a scale, shifting one meant that every other color after it had to follow, and this triggered a cascade of alt-tabs and copy pastes. Every deliberation turned into an arduous choreography.&lt;/p&gt;
&lt;p&gt;The first version of dtg cut each iteration down to the time required to change a value and save a file. Subsequently, I found myself with an interesting visual problem. I’d been staring at a well-balanced dark-mode palette and something felt a bit off. After several weeks of staring, I realized that the whole palette was a tad too green. I could’ve edited the definition file by hand, but picking the new color required some finesse. With a slight detour into versions 0.3 and 0.4, I could now fire up the editor, open the color picker, make changes and see Mosaic (my design system) hot reload immediately. I found that the sweet spot is in reducing the RGB green channel from 28 to 25.&lt;/p&gt;
&lt;figure class=&quot;image iframe-embed no-border&quot;&gt;&lt;div class=&quot;embed-frame&quot; style=&quot;aspect-ratio: 16 / 9;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/-f9hLUmEyJY?si=sPTM_iG5fpdXaJw5&quot; title=&quot;YouTube video player&quot; width=&quot;960&quot; height=&quot;540&quot; frameborder=&quot;0&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;That’s why I built dtg. Storing the recipes rather than just the color values lets me tweak them and immediately see the results. It makes a laborious process simple. And because the basics are now simple, it allows for much more discretion and sophistication in how color systems can be built.&lt;/p&gt;
&lt;p&gt;I’ve now connected the editor to &lt;a href=&quot;https://fifthrevision.github.io/mosaic/#/colors&quot;&gt;Mosaic’s public colors page&lt;/a&gt;, so you can try that part yourself. Open the hues palette, click the theme swatch, change its hue, and then look at the Button page. You’re editing the colors of a working design system, with components there to judge the result.&lt;/p&gt;
&lt;p&gt;I think of it as a variables panel for colors in software projects. It’s open source; &lt;a href=&quot;https://github.com/johncch/dtg&quot;&gt;the code is here&lt;/a&gt; if you want to see how it works.&lt;/p&gt;</content:encoded><category>writing</category></item><item><title>dtg 0.4</title><link>https://fifthrevision.com/micro/2026/dtg-0_4.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/dtg-0_4.html</guid><pubDate>Mon, 26 Oct 2026 17:48:00 GMT</pubDate><content:encoded>&lt;p&gt;This &lt;a href=&quot;https://github.com/johncch/dtg/releases/tag/v0.4.0&quot;&gt;release&lt;/a&gt; has three main changes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A much improved onboarding experience. Better readme, more sensible vocabulary, and &lt;code&gt;dtg init&lt;/code&gt; writes a working definition with the option to start with the &lt;a href=&quot;https://github.com/johncch/dtg/tree/main/examples&quot;&gt;Material or Tailwind examples&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;UI and UX improvements to the editor. Yes, it’s just called the editor now (invoked with &lt;code&gt;dtg edit&lt;/code&gt;). Particular attention was paid to how the color picker behaves and functions.&lt;/li&gt;
&lt;li&gt;An important under-the-hood change: colors are now stored as unbounded OKLab values and each algorithm decides which math space to compute in. Previously, dtg guessed a color space from how the inputs were written and converted everything to it before computing. That could clip wide-gamut colors, and colors written in different notation could produce different results. Gamut now only matters on output.&lt;/li&gt;
&lt;/ol&gt;
</content:encoded><category>micro</category></item><item><title>dtg 0.3</title><link>https://fifthrevision.com/micro/2026/dtg-0_3.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/dtg-0_3.html</guid><pubDate>Mon, 19 Oct 2026 18:16:00 GMT</pubDate><content:encoded>&lt;p&gt;Version 0.3 of &lt;strong&gt;dtg&lt;/strong&gt; is out. Check it out on &lt;a href=&quot;https://github.com/johncch/dtg&quot;&gt;GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This is a substantial release. By &lt;a href=&quot;/writing/2026/Introducing-Design-Tokens-Generator.html&quot;&gt;the end of 0.2&lt;/a&gt;, I knew that the next version would entail major changes. I didn’t appreciate their extent until the work was underway:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A new top-level &lt;code&gt;palette&lt;/code&gt; keyword in the definition file&lt;/strong&gt;. Palettes collect colors into a set for viewing and manipulating. They are for an earlier, more exploratory stage of color work, where designers puts colors side by side and adjust them until they work well together. Palettes also serve as inputs to &lt;code&gt;roles&lt;/code&gt; and &lt;code&gt;systems&lt;/code&gt;, and replace the use of &lt;code&gt;constants&lt;/code&gt; today.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System addressing now uses method parameters instead of paths&lt;/strong&gt;. Use &lt;code&gt;sky(3 tint)&lt;/code&gt; instead of &lt;code&gt;sky/3/tint&lt;/code&gt;. Dot notation is still used for traversal, e.g., &lt;code&gt;warm-wash.red(6)&lt;/code&gt;. This syntax makes it easier to distinguish what’s being used from what’s being configured, while more closely resembling CSS color functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A simpler set of out-of-the-box algorithms&lt;/strong&gt;. &lt;code&gt;ink-ramp&lt;/code&gt; became &lt;code&gt;tint&lt;/code&gt;, &lt;code&gt;oklch-scale&lt;/code&gt; became &lt;code&gt;scale&lt;/code&gt; and &lt;code&gt;blend&lt;/code&gt; was removed by a group of &lt;code&gt;tint&lt;/code&gt; systems. The algorithms are also more focused, with simpler interfaces and fewer responsibilities. Definitions are more concise, and output is now explicitly controlled by the definition file rather than the algorithms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modes support color-scheme and inheritance&lt;/strong&gt;. Modes can now be associated with light or dark color schemes, and they can inherit from other declared modes as well. This makes it easier to build related themes, including high-contrast variants or themes that differ by only a handful of colors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edit the definition file through the bundled web editor&lt;/strong&gt;. As much as I like the syntax, color work is fundamentally visual. In 0.2, the web editor let you preview colors and how they are used. In 0.3, it supports editing and saving directly. I’ve paid particular attention to the color picker, making it easy to adjust colors, especially when working with &lt;code&gt;dtg dev --build&lt;/code&gt;. A few things are still missing before it is possible to author a definition file from scratch, but we’re getting there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality of life updates to the web editor&lt;/strong&gt;. Systems can now be simulated without requiring a reference. Color scales are displayed more clearly, and hovering over any swatch reveals its color information.&lt;/li&gt;
&lt;li&gt;And tons of changes to smooth out the rough edges while using &lt;code&gt;dtg&lt;/code&gt;:
&lt;ul&gt;
&lt;li&gt;The config file &lt;code&gt;dtg.yaml&lt;/code&gt; is renamed to &lt;code&gt;dtg.config.yaml&lt;/code&gt; so that it’s both more differentiated from the definition file, and closer to other config files inside a codebase.&lt;/li&gt;
&lt;li&gt;There is no longer a default path for definition files. Specify them in the config file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dtg emit&lt;/code&gt; becomes &lt;code&gt;dtg build&lt;/code&gt; and the &lt;code&gt;--live&lt;/code&gt; flag got renamed to &lt;code&gt;--watch&lt;/code&gt; to align the verbs to other tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The CLI can also generate static pages for publishing (&lt;code&gt;dtg docs --out &amp;lt;dir&amp;gt;&lt;/code&gt;). Here are &lt;a href=&quot;/colors/index.html&quot;&gt;the colors&lt;/a&gt; that fifthrevision uses, along with &lt;a href=&quot;https://fifthrevision.github.io/mosaic/#/colors&quot;&gt;a preview&lt;/a&gt; of Mosaic’s (my design system) colors and component library.&lt;/p&gt;
&lt;p&gt;Truthfully, we’re still in the early stages of the project, where many of the building blocks are still being reconsidered and refined. &lt;mark&gt;Version 0.2 demonstrated the value of a color tool that captures how colors are derived. Version 0.3 focused on making the idea practical, with a coherent foundation and usable interface.&lt;/mark&gt; The basic shape should now be largely stable, with fewer breaking changes going forward. The focus for the next release will be on from-scratch authoring and extension points, as well as support for gradients.&lt;/p&gt;
&lt;p&gt;This tool has been invaluable to me and my coding agents as we iterate on Mosaic, and hopefully it will be for you as well.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Axle release 0.33 and 0.34</title><link>https://fifthrevision.com/micro/2026/axle-33-and-34.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/axle-33-and-34.html</guid><pubDate>Mon, 12 Oct 2026 05:11:00 GMT</pubDate><content:encoded>&lt;p&gt;I should make a habit of writing about releases when they come out. The weekly cadence means announcements sometimes get bunched up.&lt;/p&gt;
&lt;p&gt;0.33 and 0.34 are substantive &lt;a href=&quot;https://github.com/johncch/axle&quot;&gt;Axle and CLI&lt;/a&gt; releases that let me acheive a personal milestone: I have a agent doing financial research on a schedule and sending me a text message with recommendations.&lt;/p&gt;
&lt;p&gt;On the CLI side, 0.33 added scheduling to Axle CLI on macOS via launchd. Tasks can now run on interval or schedule through the &lt;code&gt;axle schedule&lt;/code&gt; subcommand, and can be retrieved using &lt;code&gt;session&lt;/code&gt; and resumed as other Axle sessions. To make this useful, every CLI recipe gets a tool set unless specified.&lt;/p&gt;
&lt;p&gt;0.34 completes the scenario above by adding Skills. CLI now supports the &lt;a href=&quot;https://agentskills.io/home&quot;&gt;Agent Skills&lt;/a&gt; spec. Drop a skill in your local &lt;code&gt;.axle/skills&lt;/code&gt; or &lt;code&gt;.agent/skills&lt;/code&gt; folder and Axle will pick it up. Then, there are a lot of other changes under the hood to make sure the shape and ergonomics are right.&lt;/p&gt;
&lt;p&gt;On Axle core itself, 0.33.0 and 0.34.0 bring in a grab bag of improvements. Skill support as a first class Agent concept. Pending Turns show up on &lt;code&gt;Transcript&lt;/code&gt;, making it simple to render queued messages. New lifecycle hooks (async &lt;code&gt;onSettled&lt;/code&gt; and &lt;code&gt;onIdle&lt;/code&gt;) on the Agent object enable better lifecycle interactions. The static model registry got replaced with a dynamic one backed by &lt;a href=&quot;https://models.dev&quot;&gt;models.dev&lt;/a&gt; so that consumers can look up real-time model info and pricing. There are tons of work under the hood as well: stability, robustness, protocol improvements, as well as a few breaking changes coming from implementing better mental models. Building a library is a process of understanding the problem, and then understanding the problem over and over again*.&lt;/p&gt;
&lt;p&gt;And oh, TypeSafe’s decision API is in Core as experimental. I’m looking forward to integrating it as a first-class citizen for classification into Agent – more on that soon.&lt;/p&gt;
&lt;p&gt;Full release notes can be &lt;a href=&quot;https://axle.fifthrevision.com/changelog#_0-34-0-2026-10-10&quot;&gt;found here&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Goodbye Jekyll, hello Astro</title><link>https://fifthrevision.com/micro/2026/goodbye-jekyll-hello-astro.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/goodbye-jekyll-hello-astro.html</guid><pubDate>Tue, 06 Oct 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The first commit of this version of the website happened in February 2017 (169e91e7). It went from a set of handcrafted HTML and CSS files (edit: I was wrong, it &lt;a href=&quot;/writing/2020/redesign-circa-2020.html&quot;&gt;was a Wordpress site!&lt;/a&gt;) to a site statically generated with &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Jekyll gave me the vocabulary and the confidence to do bigger things. The loose collection of pages turned into a coherent set of essays and portfolio entries. Then, a reading list and reviews I would write of them (that ended up being a tough thing to keep up on). Later, a microblog.&lt;/p&gt;
&lt;p&gt;In the last few years, I’ve noticed creakiness in the Jekyll ecosystem. Once, I upgraded the Ruby version and the build broke. Plugins stopped getting maintained (I’m looking at you, &lt;a href=&quot;https://github.com/sverrirs/jekyll-paginate-v2&quot;&gt;jekyll-paginate-v2&lt;/a&gt;). Liquid 4.x is limited in what it can express (5.x looks like &lt;a href=&quot;https://github.com/jekyll/jekyll/pull/8662&quot;&gt;it’ll never get supported&lt;/a&gt;). Lastly, I’m not a Ruby person and I don’t want to maintain custom extensions.&lt;/p&gt;
&lt;p&gt;Recently, I’ve used &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; for a few &lt;a href=&quot;https://axle.fifthrevision.com/&quot;&gt;content-heavy&lt;/a&gt; &lt;a href=&quot;https://www.sunnyday.run&quot;&gt;static sites&lt;/a&gt; and I liked what I saw. Well, first and foremost, I’m a TypeScript person. My requirements for this site remain the same: static-site generation primary, JavaScript as an enhancement layer, and building on top of a variety of content types. Back then, I flirted with the idea of porting the site to Astro, but the idea of undoing years of technical debt felt daunting so I never took the next step.&lt;/p&gt;
&lt;p&gt;Yesterday, I bit the bullet and ran the migration using Claude Code. It was done in a few hours with Fable 5.1 driving Opus 5.5 subagents and the entire process went as smoothly as one can hope. Layouts went from Liquid to Astro components. The content folders became more sane; it’s interesting how many Jekyll conventions can quickly become limitations once the use cases outgrow what they were designed for. I took the opportunity to convert SCSS to plain old CSS — CSS is mostly at parity these days with a few features in the pipe. The codebase reads better, runs better (no more fumbling with bundler, why no run scripts?), and the generated output is basically byte-identical.&lt;/p&gt;
&lt;p&gt;Then, I shipped my first site change in years, a &lt;a href=&quot;/projects/index.html&quot;&gt;revamped projects list&lt;/a&gt;. Which is to say, fifthrevision is now officially on Astro. So far so good! I’m sure I’ve traded one set of constraints for another. Time will tell.&lt;/p&gt;
&lt;p&gt;For nearly a decade, you served me well. Thank you, Jekyll.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Anti-social social technology</title><link>https://fifthrevision.com/micro/2026/anti-social-social-technology.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/anti-social-social-technology.html</guid><pubDate>Wed, 30 Sep 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The first question we ask of a new technology is &lt;em&gt;what can this product do for me&lt;/em&gt;. It’s a useful lens for evaluation, and AI is right in the middle of answering that: do my work, read my emails, write my docs, achieve my dreams, yada yada.&lt;/p&gt;
&lt;p&gt;The question seldom asked is &lt;em&gt;what can this product do for the other&lt;/em&gt;. How do we make it easier for the other person to understand us? How do we take the burden off other people that we work with? How do we help other people? Much of what we use today don’t arrive at this stage of questioning.&lt;/p&gt;
&lt;p&gt;AI is poised to be the most transformative technology in my lifetime. It is also, so far, a Randian ideal: it accentuates differences and reinforces individual preferences. However, we are social creatures who rise and fall together. So the imperative question we should all be asking at the moment, designer or not, is &lt;em&gt;what can this technology do for us&lt;/em&gt;.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>This week: Axle 0.31, 0.32</title><link>https://fifthrevision.com/micro/2026/this-week-0915.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0915.html</guid><pubDate>Tue, 15 Sep 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I haven’t posted an update in a while because I took a vacation and had to work for money! That said, Axle shipped a few minor versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Axle 0.31.0 shipped a major CLI revamp. This update took everything I’ve learned building apps with Axle and put it into a modern, usable TUI. In addition to the new UI, Axle CLI now supports follow up interactions and resumable sessions, as well as more sensible configuration and setup.&lt;/li&gt;
&lt;li&gt;Axle 0.32.0 reworked the thinking Turn and stream objects. It’s a minor but breaking change to the format. The implementation of thinking has always been a little janky, and the recent release of Muse Spark 1.3 gave me a chance to revisit it so that it’s a little cleaner.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m personally pretty pleased with the CLI updates. This resolved a few longstanding issues I had with the previous implementation, including the fact that it was just really ugly. With the open weight models being quite cheap and good these days – I’m really liking GLM 5.3 Flash – I’m harboring a few automation fantasies on my life. Not quite there yet, a few more gaps to close, but I’m hoping to have some updates soon.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Store colors as algorithms not hexes</title><link>https://fifthrevision.com/writing/2026/Introducing-Design-Tokens-Generator.html</link><guid isPermaLink="true">https://fifthrevision.com/writing/2026/Introducing-Design-Tokens-Generator.html</guid><description>Introducing dtg, a design token generator for color systems</description><pubDate>Sun, 13 Sep 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;lead-in&quot;&gt;I’ve been thinking a lot&lt;/span&gt; about colors recently. It is one of the first things I do when starting a new design project, and one of the things that goes through iterations as the project progresses. Colors express much that is difficult to quantify: information, fashion, mood, and many other intangible qualities that make software feel comfortable or hostile. Color systems can be difficult to work with; the reasoning behind the systems is often opaque, and they are deeply embedded in apps and tools. I’ve been working on a tool for myself called &lt;a href=&quot;https://github.com/johncch/dtg&quot;&gt;dtg&lt;/a&gt; (Design Token Generator), which I hope will lessen the work of iterating on colors, and increase the satisfaction of doing so.&lt;/p&gt;
&lt;h2 id=&quot;how-i-generate-colors&quot;&gt;How I generate colors&lt;/h2&gt;
&lt;p&gt;I used to start projects by generating a palette at &lt;a href=&quot;https://coolors.co/&quot;&gt;coolors.co&lt;/a&gt; and turning it into color scales via an online Tailwind color scale generator. I first saw this with Google’s Material Design, and Tailwind was where I had the most first-hand experience. It was a step up from picking arbitrary colors, but I found the gradations limiting. It felt like painting with a limited set of crayons.&lt;/p&gt;
&lt;p&gt;Over the years, my process gained a few new tricks: I started creating different color scales for different uses, breaking away from the 50-950 steps; I started blending colors in different proportions within a single scale; and I started computing colors in OKLCH so a move in lightness reads the same whether the hue is yellow or blue. One of the benefits of varying color scales based on semantic meaning is that we can use colors to build structure instead of relying solely on signposts. We have a natural acuity for visualizing surfaces and depth, and color systems should take full advantage of that.&lt;/p&gt;
&lt;figure class=&quot;image &quot;&gt;&lt;a class=&quot;zoom&quot; href=&quot;/assets/images/posts/26-09-13/layers@2x.png&quot; target=&quot;_blank&quot;&gt;&lt;img class src=&quot;/assets/images/posts/26-09-13/layers.png&quot; srcset=&quot;/assets/images/posts/26-09-13/layers@2x.png 2x&quot; alt=&quot;A screenshot of the Agent Configuration screen in Sunnyday&quot;&gt;&lt;/a&gt;&lt;figcaption&gt;&lt;p&gt;Sunnyday has a particularly dense UI which benefits from tweaking the nuances of how surfaces layer upon each other. I want to say I did a good job.&lt;/p&gt;
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The challenge with this approach is that the work is no longer simple. And this leads to two broad problem areas:&lt;/p&gt;
&lt;p&gt;First, color systems are rarely one-and-done. We often need to make adjustments to accommodate new uses or change how the product feels. Because there are different algorithms for each scale, and they are all anchored on different colors, &lt;em&gt;and&lt;/em&gt; they are often blended on a graphics tool, tweaking one requires going through the entire motion to generate the new hexes. Furthermore, documentation is often an afterthought, and the method for generating the color is stuck in a Figma file from years ago or no longer preserved.&lt;/p&gt;
&lt;p&gt;Second, keeping colors in sync between the various tools that I use is a frustratingly menial job. As an illustration, if I need to add a new in-between color, I need to go into Figma to add the color, make any name changes, ensure that one-off colors are updated properly, and then do the same in every software project where the colors are used. The complexity increases exponentially with the sophistication of color generation, and over time I get bogged down in the minutiae.&lt;/p&gt;
&lt;p&gt;These little speed bumps make band-aid fixes so much more tempting. New colors get added arbitrarily: why not just pick an arbitrary one and go? Tokens drift because it’s easier to just eyeball it in the codebase. Swapping color references to avoid rejigging the scale. The system that was once coherent turns discordant.&lt;/p&gt;
&lt;h2 id=&quot;keeper-of-yellows&quot;&gt;Keeper of yellows&lt;/h2&gt;
&lt;p&gt;I had a thought the other day: what if the methodology for generating colors could be recorded and reproduced. What if adding a new color would then be as easy as pointing to another point on that continuum. And lastly, what if all changes synced and perpetuated across all usages effortlessly.&lt;/p&gt;
&lt;p&gt;These gave rise to the utility &lt;code&gt;dtg&lt;/code&gt;. &lt;a href=&quot;https://github.com/johncch/dtg&quot;&gt;dtg&lt;/a&gt; is a tool that lets designers express color systems in algorithms, describe how they generate into variables, and sync those variables across the tools and codebases that use them.&lt;/p&gt;
&lt;p&gt;Let’s dive into an example. These days, I’m obsessed with color scales that start at a certain color but tint shift into a new tone as they move along a brightness scale. In Sunnyday’s light mode, I have a very light blue surface that gets cooler as it darkens. Inside of dtg, I declare a &lt;code&gt;tint&lt;/code&gt; algorithm named &lt;code&gt;sky&lt;/code&gt; with a base of &lt;code&gt;#fcabda&lt;/code&gt; and a tint of &lt;code&gt;#012012&lt;/code&gt;. I then have a set of semantic variable names that point to various points on the scale, such as &lt;code&gt;sky(15)&lt;/code&gt;, where the selector (the &lt;code&gt;15&lt;/code&gt;) means 15% tint over that base. The token name is the recipe.&lt;/p&gt;
&lt;p&gt;Here’s a snippet from the configuration file:&lt;/p&gt;
&lt;pre class=&quot;astro-code css-variables highlight&quot; style=&quot;background-color:var(--astro-code-background);color:var(--astro-code-foreground);overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;dtg&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-constant)&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;modes&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;light&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;systems&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  sky&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt; # a cool tint over a warm base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    algorithm&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; tint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    params&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;quot;#fcabda&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-punctuation)&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt; tint&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string-expression)&quot;&gt; &amp;quot;#012012&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;  surface&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    canvas&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;sky(0)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;# the base, with no tint over it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    card&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;sky(15)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-comment)&quot;&gt;# 15% tint over the base&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;    floating&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-keyword)&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-token-string)&quot;&gt;sky(22)&lt;/span&gt;&lt;span style=&quot;color:var(--astro-code-foreground)&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the past, I would calculate the colors once, often by creating overlapping squares in Figma, setting the opacity, picking them with the eyedropper, and then setting them into variables. Now, I declare them in a configuration file, generate the CSS file, and check it into the codebase.&lt;/p&gt;
&lt;p&gt;The beauty of this system is that if I decide that card needs to be slightly darker, I can nudge it towards &lt;code&gt;sky(16)&lt;/code&gt; or &lt;code&gt;sky(18)&lt;/code&gt; — or &lt;code&gt;sky(15.5)&lt;/code&gt;, since the selector is a coordinate on a continuous ramp rather than a position in a list. In fact, I can nudge the entire scale by 1 or 2 points or switch up the base or tint color and maintain the brightness steps. This operation is as easy as setting one number or color in the UI and looking at the updated result. Gone are the days when I had to scavenge for where the original worksheet lived, update all of them, copy everything over, and do it all over again until I got to what I want. The iteration cycle is night and day.&lt;/p&gt;
&lt;p&gt;An upside of this approach is that since the color scale is now defined in a continuous spectrum, we can have infinite mappings and different step sizes between the different variables. In Sunnyday alone, I have more than 15 uses of the &lt;code&gt;sky&lt;/code&gt; tint with step sizes ranging from 0.5% to 15% between them. This lets me really fine-tune the relationships between adjacent surfaces, as opposed to leaving them to the mercy of a discrete, fixed-step scale.&lt;/p&gt;
&lt;p&gt;Last but not least, because colors are directly materialized into their use sites, it becomes simpler to keep them in sync between all the different tools. As an example, in the past when I had to rejigger a color scale it was a nightmare, because I had to first update the primitives, find every other variable that pointed to it and make sure they were still right, and then do the same in the codebase. Mapping this in dtg generates a more comprehensive list, but because the mappings are semantic, AI can compare the list against all the surfaces and confirm it’s up to date.&lt;/p&gt;
&lt;p&gt;I have converted this website and &lt;a href=&quot;https://www.sunnyday.run&quot;&gt;Sunnyday&lt;/a&gt; to dtg and can confirm that it works really well. For Sunnyday, it cut the iteration time I described above from days to minutes. For fifthrevision, every theme went from a set of arbitrary, unmanaged colors into a single set generated by a fixed algorithm, which is much easier to maintain. It also means I no longer have to go hunting for the arcane Figma file where it all originated every time I want to make a change.&lt;/p&gt;
&lt;h2 id=&quot;bells-and-whistles&quot;&gt;Bells and whistles&lt;/h2&gt;
&lt;p&gt;Other features in dtg cover additional things you might want your color system to do. There are ways to generate directly addressable color scales like blue 50-950. The &lt;code&gt;scale&lt;/code&gt; algorithm blends out from a base in OKLCH toward a light and a dark target, and like the tint, its selector is a coordinate on a continuous curve, so a palette in steps of 50 or an uneven ramp is just a different list of points.&lt;/p&gt;
&lt;p&gt;Another cool feature that falls out of algorithmic generation is the ability to twin opaque and transparent colors. &lt;code&gt;sky(15)&lt;/code&gt; on the &lt;code&gt;tint&lt;/code&gt; algorithm materializes a color that has 15% of the tint composited over the base; &lt;code&gt;sky(15 tint)&lt;/code&gt; generates the tint as a 15% alpha only. This is especially useful for separators and hovers that may have to sit over unknown surfaces. Finally, there is support for overrides and color pinning. These values sit in the definition next to the system they bend, and they survive regeneration.&lt;/p&gt;
&lt;p&gt;The rest of dtg is quality-of-life stuff. &lt;code&gt;dtg build&lt;/code&gt; can write any supported variable format, including CSS, SCSS, Tailwind v4, and DTCG. Then there’s a web server, &lt;code&gt;dtg dev&lt;/code&gt;, that renders a web app where palettes are displayed in their full glory: the OKLAB delta E between adjacent steps, which roles demanded each step, side-by-side comparisons, color modes, etc. I’m especially excited for this since it really takes color work to the next level. Designers should be able to go in and use all the tools at their disposal to tweak the colors to their heart’s content. As of 0.3.0, edits made there write back to the definition, so the entire lifecycle is complete.&lt;/p&gt;
&lt;p&gt;I have a few ideas for immediate next steps: supporting per-project custom algorithms, gradients and more complex color definitions. I’ve also considered non-color tokens like font ramps and corner radii, but I’m going to focus on making the color experience first-rate before covering the rest of the design system.&lt;/p&gt;
&lt;p&gt;That’s where 0.2.0 is at the moment. The project is &lt;a href=&quot;https://github.com/johncch/dtg&quot;&gt;open source and freely available on GitHub&lt;/a&gt;. Please use it, tell me what you want dtg to do, and go out and make some kick-ass design systems.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Updated Oct 16 to reflect the reworked syntax. Release 0.3.0 refined both the file structure and addressing mechanism with plenty of new features for building and editing!&lt;/em&gt;&lt;/p&gt;</content:encoded><category>writing</category></item><item><title>Intelligence and behavior</title><link>https://fifthrevision.com/micro/2026/intelligence-and-behavior.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/intelligence-and-behavior.html</guid><pubDate>Wed, 26 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There has been constant fighting with the latest crop of AI models.&lt;/p&gt;
&lt;p&gt;A few things I’ve noticed: AI models are much more eager to jump in and do instead of understand what you want. When they write, the output is jargon-filled and convoluted. Worst of all, the recent Opus 5 just flat out make things up; over the last few weeks, I’ve had multiple incidents where after I push on a specific point in a plan, the model tells me that it made a mistake and acquiesces.&lt;/p&gt;
&lt;p&gt;While none of this is indicative of intelligence per se, these behaviors make the model unpleasant to use. It feels as if they don’t understand my goals, try to paper over subpar decisions, and the most egregious of all, lie. I know I’m using people words here, ascribing intentionality to floating point numbers computed across arrays of special-purpose silicon. However, language is inherently anthropomorphizing; it is what we use to express and communicate with each other, and now with computers.&lt;/p&gt;
&lt;p&gt;The thing is, none of this is &lt;em&gt;inherent&lt;/em&gt; to the mathematical properties that create artificial intelligence. This is all trained behavior. My guess is that the pursuit of AI models that perform well on benchmarks and long-horizon tasks that leads to choosing verifiable rewards over human feedback creates behaviors that look like this. Inattentive and dismissive.&lt;/p&gt;
&lt;p&gt;I’ve long thought that intelligence is not a linear measure. I had a conversation recently with a friend about this where I argued that preferences–for example in language and art–are not something that can be captured by &lt;a href=&quot;https://en.wikipedia.org/wiki/Neural_scaling_law&quot;&gt;scaling laws&lt;/a&gt;. He disagrees. I was arguing that there are different dimensions to intelligence and maxxximizing one will diminish others. A better way to frame it would be to separate what it can do versus how it behaves.&lt;/p&gt;
&lt;p&gt;Perhaps soon, people will start talking about IQ vs EQ again. Perhaps one day AI model makers will find the right balance between the know-it-all and the we-get-you. But I’m not holding my breath.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>This week: dtg and company</title><link>https://fifthrevision.com/micro/2026/this-week-0823.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0823.html</guid><pubDate>Sun, 23 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I spent a good part of this week working on a color system to token tool called &lt;code&gt;dtg&lt;/code&gt;. It’s a somewhat niche tool that solves a long standing problem that I have. I’ll have more to say about it shortly, but suffice to say, I’m real stoked about it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/johncch/axle&quot;&gt;Axle got a 0.30.2 bump&lt;/a&gt;. Bug fix and a refinement to the prompt compactor API. It feels pretty good now. I’ve been test driving &lt;a href=&quot;https://github.com/johncch/axle-code&quot;&gt;axle-code&lt;/a&gt; on the new stealth model on open router, ox alpha, and I’m overall really happy with how rock solid Axle is. Occasionally, I wished that I can compile typescript down to binary (yes I know about &lt;a href=&quot;https://github.com/vercel-labs/scriptc&quot;&gt;scriptc&lt;/a&gt;) just to really get access to real multithreading, but as it stands everything is fast enough.&lt;/p&gt;
&lt;p&gt;Speaking of ox alpha, rumor has that it’s a GLM or GLM-based fine tune. It definitely has some Claude-isms in the text it emits (and less so GPT-isms). After running it for a bit, I’ll pin it at around a below Sonnet, above Haiku level of intelligence. In my subjective measure, coding ability is be inversely proportional to the amount of frustration I feel while using it. This new model often runs itself into a quagmire and needs me or a better model to bail it out; this is the first time I’ve had to revert my git history while using an AI agent.&lt;/p&gt;
&lt;p&gt;I’m making little progress on the eval work that I’ve been mulling on. The approach that I’m taking — a test harness vocabulary built on knobs on LLM as a judge – feels like a dead end. It all still feels like syntactic sugar and not a meaningful step forward. Part of it is that it’s really hard to know what correct means over a long horizon, the other is that even if I do, I don’t know if I could trust it without seeing it.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>This week: Axle 0.30, new docs; Sunnyday gains skills</title><link>https://fifthrevision.com/micro/2026/this-week-0816.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0816.html</guid><pubDate>Sun, 16 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/@fifthrevision/axle/v/0.30.1&quot;&gt;Axle 0.30&lt;/a&gt; is a big milestone in a few ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It marks the 30th release since I’ve started publishing the library consistently since June of last year. I typically release when I need to integrate changes into my core projects, and minor releases are when I make significant additions or breaking changes. That’s quite a pace, if I may say so myself.&lt;/li&gt;
&lt;li&gt;More importantly, the &lt;code&gt;compaction&lt;/code&gt; API has arrived at a good place. 0.30 solved a design conundrum I’ve been facing for a while, that is, what is the role of History — the dual objects of Messages and Turns — when it can be modified by an external actor. The answer is by removing Turn, the presentation layer, out of the Agent, and reduce the surface area of data that Agents work with. Now, the data model is coherent with a bit of conceptual tradeoff which we can bridge with built-in functions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To celebrate, and to make sure I’m explaining the conceptual model well, the &lt;a href=&quot;https://axle.fifthrevision.com&quot;&gt;documentation site&lt;/a&gt; got a content revamp.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sunnyday.run/&quot;&gt;Sunnyday&lt;/a&gt; shipped skills. It’s something I’ve been wanting to do for a while, and having a concrete use case finally gave me a reason to built it.&lt;/p&gt;
&lt;p&gt;The implementation went through a couple of cycles. The starting point was simple enough: it walks like a file and quacks like a file. But it soon became apparent that skills do indeed have a special status in an agent platform. I’ve settled on treating skills as files in the UI while handling them differently on the backend, which let’s me keep the UI and entry points simple. Though I doubt this is the last time I’ll have to think about it.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>This week: Sunnyday Sandbox resume, Assistant; next Axle CLI?</title><link>https://fifthrevision.com/micro/2026/this-week-0809.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0809.html</guid><pubDate>Sun, 09 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On the &lt;a href=&quot;https://www.sunnyday.run&quot;&gt;Sunnyday&lt;/a&gt; side:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent sandboxes per session are fully resumable now, up to a maximum of 30 days. This sets up each agent up to take follow up commands, which will open up new avenues of interacting and correcting remote agents&lt;/li&gt;
&lt;li&gt;Assistant is now in beta. You can now prototype, create, and update Agents using the Assistant. This is something I’ve been mulling on for a while; as much as I think the UI is remarkably intuitive, the blank screen problem is still tricky to design around. This provides a way to turn sketches into infrastructure builds really quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because the work was based on &lt;a href=&quot;https://www.github.com/johncch/axle&quot;&gt;Axle&lt;/a&gt; (we shipped an update for this around the internal ontology — 0.29.0), and most of the work took advantage of features in Axle recently, it was quick to come together. For me, this sets up some further thinking around conversations as the primary UI that I’ve been mulling about, and I believe will make some of the deeper cutting features, such as self-serve custom evals, possible. AI Agents are very good at pulling existing snippets together.&lt;/p&gt;
&lt;p&gt;I’ve been thinking about the next iteration of axle-cli. I’ve been building &lt;a href=&quot;https://github.com/johncch/axle-code&quot;&gt;axle-code&lt;/a&gt; for fun on the side, and it has been illuminating to see what features require more work (harness) and what works “out of the box”. Spoiler alert: frontier AI models are coding models by default. I am going to need a more sophisticated CLI soon: it’s going to look a bit like Cowork but with the conveniences of task runners. More to come!&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Prototyping the SDLC</title><link>https://fifthrevision.com/micro/2026/prototyping-the-sldc.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/prototyping-the-sldc.html</guid><pubDate>Wed, 05 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;AI generates code an order of magnitude faster than any human can. Hand-writing code is no longer a tenable proposition, and so the effort has shifted to doing whatever we can to hold AI code to our own quality bar. Some hand wave it away, comparing it to the evolution of C over Assembly, arguing that over time AI is going to be so good that we never have to think about the lower level code anymore. Others reach for the dark factory, where we validate the inputs and outputs and never care about what happens in between. The most developed version of this is a methodology now, promising to turn &lt;a href=&quot;https://x.com/karpathy/status/1886192184808149383&quot;&gt;vibe coding&lt;/a&gt; into &lt;a href=&quot;https://www.kaggle.com/whitepaper-the-new-SDLC-with-vibe-coding&quot;&gt;agentic engineering&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve written about the &lt;a href=&quot;/micro/2026/the-law-of-conservation-of-complexity.html&quot;&gt;conservation of complexity&lt;/a&gt;. The desired output is functionality, and the burden of knowing the details and verifying that it performs to the standard is something that still needs to be performed. In the agentic engineering case, the work shifts from software design and planning to a combination of bringing in the relevant contexts, using the appropriate set of prompt incantations, asking all the right questions, and rigorous testing.&lt;/p&gt;
&lt;p&gt;I can see the allure. With the right process and guardrails, we can coerce AI to produce quality software. That said, the fragility of quality is often due to established processes being upended by unknowns, and it is impossible for us or anyone to know everything ahead of time. If the price of producing software approaches zero, we can take inspiration from practices from a recent past: prototyping.&lt;/p&gt;
&lt;p&gt;In a formal Design process, we use prototypes extensively to validate desired behaviors and outcomes, which then gets handed over to the engineering process. Why not extend the idea: use AI to create prototypes, learn, and then generate specs, validation, and tests from them. More importantly, we discard the prototypes and rebuild the code from ground up using these produced artifacts. If anything changes with the artifacts, we discard the code and generate it from ground up again.&lt;/p&gt;
&lt;p&gt;This separation between spec generation and code generation is important. A lot of bugs in software happen because of workarounds accumulated over time. Instructing AI to “make small changes” sounds good until it becomes a volley of patches layered on top of each other that becomes impossible to reason about.&lt;/p&gt;
&lt;p&gt;This might sound a tad radical in a “we’ll rewrite it later” never world. However, consider the strengths of an AI agent: they are able to endlessly and tirelessly transform a set of words into another and conform them to an infinite suite of tests. Perhaps if production code is only produced with clean and locked down specs, we can maintain the rigor required of an industrial process. And notice the trick here, a fully deterministic set of requirements that produces a verifiable set of outputs sounds like a compiler. In the course of the rise of generative AI, we’ve been endlessly, tirelessly trying to coax probabilistic AI into deterministic outcomes, and maybe one day we will succeed.&lt;/p&gt;</content:encoded><category>micro</category></item><item><title>This week: Sunnyday pruning; codebase knowing.</title><link>https://fifthrevision.com/micro/2026/this-week-0802.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0802.html</guid><pubDate>Sun, 02 Aug 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The week was all about trimming and pruning. Sunnyday went through an AI code review and came out with roughly a thousand lines less. Most of the savings came from the deletion of duplicated logic, and many of that from AI code written across different sessions.&lt;/p&gt;
&lt;p&gt;I prefer a well refactored codebase because it simplifies the mental model that I have to hold in my head. AI doesn’t have to do that, it is tireless in how it reads and spits out code. That said, none of us are immune from the effects of a sprawling codebase—losing track of what things are supposed to be and subtle differences across branches.&lt;/p&gt;
&lt;p&gt;I think a lot about the speed-knowledge tradeoff these days. If I go fast, which I can go much faster than I am today, I truly lose sight of what goes into my codebase. I maintain some oversight on code input, at least in codebases that I care about, and even then I’m surprised by some of the decisions when I do code review. Do we end up in a world where the discipline reorganizes itself into an outside looking in motion? Attention is truly the scarce resource of our age.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>A Framework for Agentic Success</title><link>https://fifthrevision.com/micro/2026/framework-for-agentic-success.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/framework-for-agentic-success.html</guid><pubDate>Tue, 28 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I wrote this down a few months ago while working on &lt;a href=&quot;https://www.sunnyday.run&quot;&gt;Sunnyday&lt;/a&gt;. Recording here for posterity.&lt;/p&gt;
&lt;p&gt;There are 4 levels to understand if an agentic trace was &lt;em&gt;successful&lt;/em&gt;. It breaks down to the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L0: did the run complete?&lt;/strong&gt; These are binary outcomes at the infra level, basically if there are errors at the infrastructure level that prevented a run completion. Common examples are whether the LLM provider is at capacity, less obvious ones can be an example of a misconstructed tool call that loops forever.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L1: did the agent do what it planned?&lt;/strong&gt; At this level, we ask the AI agent to pre-register what it thinks it’s going to need to do based on the information that is available at the message. Then we grade the completed run against the plan to check for gaps that we can fill in earlier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L2: did it do the work well?&lt;/strong&gt; Independent of the plan, did the agent encounter any obstacles when doing the work. Two separate tracks here. The first is if the run was &lt;em&gt;optimal&lt;/em&gt;, where we detect for stumbling, error recovery, path efficiency, looping and flailing. Then there is the counterpart where we check if the tools and infrastructure is providing the right level of access and guidance to the agent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L3: did the customer get what they wanted?&lt;/strong&gt; This is a check on the work quality. The user started the agent to achieve a certain outcome; did the agent produce it? We start at examining whether deliverables are completed e.g., prose or pdf files, and then we can inspect the content of those things, whether they reflect the request, and furthermore we can delve into whether the content is accurate or aesthetic. This can probably be further broken down into multiple layers.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>micro</category></item><item><title>This week: Axle 0.28.0; evals, experiments.</title><link>https://fifthrevision.com/micro/2026/this-week-0726.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/this-week-0726.html</guid><pubDate>Sun, 26 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Axle 0.28.0: a release long in the making focused on completing the compaction API and steering &lt;a href=&quot;https://axle.fifthrevision.com/migration/0.28.0&quot;&gt;(changelog)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The hardest bit was finding the tradeoff sweet spot between complexity and API design. I first started with &lt;code&gt;steer()&lt;/code&gt; – an API that allows the user to send a message that both cuts the queue and inserts in the first opportunity – which I backed out off because it introduced multiple queues in the scheduling internals. The compromise was to do less internally and expose a more granular API: &lt;code&gt;stop()&lt;/code&gt; for a graceful stop, &lt;code&gt;clear()&lt;/code&gt; to empty the queue, and chaining them together with a &lt;code&gt;send()&lt;/code&gt; for steering semantics. I’m still finding the right line between opinionated and flexible; I’ll try the APIs out in a few Axle-Orbit experiments and see how they fare.&lt;/p&gt;
&lt;p&gt;Other things shipped: make Axle baseline checks run in parallel; minor updates to Sunnyday fixing bugs and bumping up models and dependency.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Evals is on my mind. Even outside of the hype, having tools to slice and dice transcripts and corpus of transcripts feels &lt;em&gt;useful&lt;/em&gt;. I’ve been thinking a lot about the how, and so far the most tenable way for me to make progress is to start bottoms up. I build a lot of fixtures to run Axle against LLM APIs as smoke tests. They are pretty rudimentary now, and perhaps iterating on those will lead me down more interesting conceptual paths.&lt;/p&gt;
&lt;p&gt;One thing I’m trying to get myself to do now is to learn by doing. I have a tendency to want to think through problems thoroughly before attempting them. That’s one way of working through a problem. But sometimes, the smart and right thing to do is to stop thinking and start chipping at it. I need more of that in my practice.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>A new resolve?</title><link>https://fifthrevision.com/micro/2026/a-new-resolve.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/a-new-resolve.html</guid><pubDate>Thu, 23 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been thinking about what kind of work I want to do next. It then occurred to me: instead of thinking about problems, I can just work on them. The cost of making is dramatically lower these days, why not spend the time trying things and getting hands-on. The trick is picking problems small enough that I can finish. I’ll write up and post my findings here, so that I actually do.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>The Law of Conservation of Complexity</title><link>https://fifthrevision.com/micro/2026/the-law-of-conservation-of-complexity.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/the-law-of-conservation-of-complexity.html</guid><pubDate>Thu, 16 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Everyone else is talking about evals these days. Unsurprisingly, since we are at the phase where AI adoption is hitting critical mass.&lt;/p&gt;
&lt;p&gt;There are two ways to know a system. You can know it from the inside, by holding the rule that generates its behavior: I built this, so I know how it works and what it will do. Or you can know it from the outside: when it does this, it needs to do that; quacks like a duck, is a duck and all that. Roughly speaking, it can be mapped to implementation versus specification.&lt;/p&gt;
&lt;p&gt;In traditional software teams, software engineering and product management are the two equivalents. With AI doing most of the software writing these days, the location of the inside knowledge gets displaced. Prior to AI, the software engineer in the code base absorbs the burden of a lot of the complexity &lt;em&gt;for free&lt;/em&gt;. AI removes the hiding spot, the thing still gets built, but no accountable human acquires the inside knowledge along the way.&lt;/p&gt;
&lt;p&gt;I want to recall &lt;a href=&quot;https://en.wikipedia.org/wiki/Law_of_conservation_of_complexity&quot;&gt;Tesler’s law of conservation of complexity&lt;/a&gt;. In Tesler’s formulation, there is a minimum amount of complexity that is either handled by the programmer or the user. In this case however, the knowledge of the complexity that is inherent to functioning software needs to be captured by implementation (inside knowledge) or verification (outside knowledge).&lt;/p&gt;
&lt;p&gt;All the chatter around evals and &lt;a href=&quot;https://www.danshapiro.com/blog/2026/01/the-five-levels-from-spicy-autocomplete-to-the-software-factory/&quot;&gt;dark factory patterns&lt;/a&gt; is about this. At the end of the day, someone needs to know that the system is doing what it’s supposed to do, and while the work is easier, I don’t know if the knowing can ever be.&lt;/p&gt;
</content:encoded><category>micro</category></item><item><title>Keeping up with the Robots</title><link>https://fifthrevision.com/micro/2026/keeping-up-with-the-robots.html</link><guid isPermaLink="true">https://fifthrevision.com/micro/2026/keeping-up-with-the-robots.html</guid><pubDate>Thu, 09 Jul 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This morning, I was multitasking. I spent a few minutes making Claude Code go, and while it’s revving I’m writing in my paper notebook. Something catches the corner of my eye, I looked up and went to tend to the AI’s request. It whirls again, so it’s back to the notebook. Back and forth. As you can imagine, neither turned out particularly well, although if I were to be fair, the robot did a much better job than my writing. After all, I was only the one multitasking.&lt;/p&gt;
&lt;p&gt;We have long known that multitasking reduces our cognitive abilities. There are &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC2747164/&quot;&gt;numerous&lt;/a&gt; &lt;a href=&quot;https://www.apa.org/pubs/journals/releases/xhp274763.pdf&quot;&gt;credible&lt;/a&gt; &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC5658797/&quot;&gt;studies&lt;/a&gt; on this topic. Yet everyone is dual or triple wielding coding agents these days. Everyone feels more productive, &lt;a href=&quot;https://fifthrevision.com/writing/2026/what-is-everyone-actually-doing-with-ai.html&quot;&gt;and they are&lt;/a&gt;. They also say the work is not better &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;My observation is that the current crop of AI coding agents and models sit in the anti-flow zone of productivity: there is a little too much down time in between prompts, yet not enough to be able to effectively do something else. Once you hit enter on a prompt, a typical coding agent can take anywhere from minutes to tens of minutes, and while it’s doing its thing there is nothing much the human observer can do. We can try to follow along, but the terminal outputs are not really comprehension friendly. Of course we get bored and we multitask.&lt;/p&gt;
&lt;p&gt;As a thought experiment, I wondered what would happen if coding agents are a magnitude faster&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. If we can get instant gratification it might solve the desire to let the attention wander. Yet at the same time, it raises an interesting question: if the robots can generate thousands of lines of code in a matter of seconds, then how are we able to really understand what’s going on? The temptation will be to do more and understand less since it’s the path of least resistance. Consequently, we will drown in systems that we do not understand.&lt;/p&gt;
&lt;p&gt;When I ask people about this, everyone says that taste is going to be the thing that differentiates them. Make sense, since our perspective and judgement is what we really bring to the table and affect the world around us. That said, to be able to render accurate judgement requires us to understand the thing that we are judging. If our comprehension is being overwhelmed, then our judgement is what’s being overwhelmed.&lt;/p&gt;
&lt;p&gt;I don’t know if there’s a neat little solution to this puzzle. My sense is that the status quo is not sustainable and things will need to change: either we develop tools to help us hold and understand more complexity, or we will have to delegate. Either the craft matters, or it becomes utilitarian.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;The specific finding did not make it into the slides, but I have jotted it down here: &lt;em&gt;Work Quality is felt to improve — except in engineering, which is neutral (3.0 vs design 3.4, PM 3.7). One hypothesis: engineers are no longer fully in charge of their craft.&lt;/em&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Anthropic shipped fast mode with Opus 4.6. Large scale mechanical refactors completed in a couple of minutes but it was expensive (6x). It almost crosses the attention span gap but wasn’t quite fast enough. I loved it though—the experience was remarkable. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded><category>micro</category></item><item><title>What Is Everyone Actually Doing With AI?</title><link>https://fifthrevision.com/writing/2026/what-is-everyone-actually-doing-with-ai.html</link><guid isPermaLink="true">https://fifthrevision.com/writing/2026/what-is-everyone-actually-doing-with-ai.html</guid><description>A survey of 107 about how people use AI</description><pubDate>Tue, 30 Jun 2026 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;lead-in&quot;&gt;About a month ago&lt;/span&gt; I asked a friend if he was using any automations as part of his daily work. In response, he said he hadn’t used much AI other than the obligatory chatbots, and that he felt behind. It made me think about what I take for granted in my own AI use, and really ignited my curiosity about how everyone else is using AI.&lt;/p&gt;
&lt;p&gt;As a designer, what do you do in these circumstances? You ask people. So, I made a survey on how people use AI at work and how they feel about it. This survey was sent to friends and a few other social and professional groups that I’m in.&lt;/p&gt;
&lt;p&gt;107 people took the survey. High level findings: people are using a lot of AI at work, and AI replaces or augments the main work that they do. Respondents like it, and most surprisingly, software engineers who use AI to do a lot of their core work still think using AI makes them more valuable. One caveat is that these respondents are AI enthusiasts, so if anything these numbers represent the leading edge, not the average. Here are the full results:&lt;/p&gt;
&lt;figure class=&quot;image iframe-embed no-border&quot;&gt;&lt;div class=&quot;embed-frame&quot; style=&quot;aspect-ratio: 960 / 569;&quot;&gt;&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vRWNahbiJx6AB7CEBlYtDCr9M7aNVFZA9ZX6sZd4uRYqk6sWrLNfkzDCk0hRiJZMd4R-v6mfr3_pAj9/pubembed?start=false&amp;amp;loop=false&amp;amp;delayms=3000&quot; title=&quot;AI At Work survey presentation&quot; width=&quot;960&quot; height=&quot;569&quot; frameborder=&quot;0&quot; allowfullscreen mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;h2 id=&quot;a-note-on-methodology-and-my-own-ai-use&quot;&gt;A note on methodology and my own AI use&lt;/h2&gt;
&lt;p&gt;This being a survey about AI, I wanted to be really cognizant about how I use AI in this process. Overall, the start to finish took over a month. A few days to write the survey. One week of procrastination. A little over two weeks of result collection, and about a week of result analysis.&lt;/p&gt;
&lt;p&gt;The initial survey was written in conjunction with Claude. I penned down a very rough first draft, fleshed out the structure with Claude, and iterated question by question until we got it tight. I knew from the beginning that the survey needed to be 15 questions or less, so the main decision points were making sure each question pulled its own weight, and balancing the types of questions so I got both comparable data points and rich insights.&lt;/p&gt;
&lt;p&gt;An important precursor to analyzing the results was registering my hypotheses. I knew that once I set eyes on the results my “findings” would be colored, so it was important to figure out what I expected. From the initial survey I got Claude to ask me a bunch of questions about my expectations. I answered each one of them and registered what I thought the answers would be. The results turned out pretty much in line with the hypotheses, differing in magnitude, with the exception of the finding above where the people who do their core work with AI still find that using AI makes them more valuable.&lt;/p&gt;
&lt;p&gt;Analyzing the results took a few passes. The first was making sense of all the quantitative responses. My tool of choice for this is Jupyter notebook, and I used Codex and Copilot to help build most of the notebook out. I first graphed out every question, then broke each one down by demographics.&lt;/p&gt;
&lt;p&gt;Once I was satisfied with all the quant data, I then took a pass on the qualitative ones. I first read them individually to get a sense of what the overall picture looked like. Then, with Claude, we coded the rows together. This was an iterative process of asking Claude to come up with the code book, me going through row by row to see if it fit, and iterating with Claude to refine both the coding and the code book. I thought this would be easy with AI; it was easier, but it was also tedious. To finish off, the transformed data was brought back into Jupyter and graphed.&lt;/p&gt;
&lt;p&gt;When everything was done, I looked through all the graphs and wrote down everything that stood out to me. After that, I handed an AI all the data and my findings, and fleshed them out. I ended up with about 3 pages of bullet points.&lt;/p&gt;
&lt;p&gt;To construct the final deck you see above, I first highlighted the most compelling findings and then worked with Claude to construct a narrative arc for a presentation. The deck was created in Google Slides by hand, alas. The charts were created in Google Sheets with data extracted from the source worksheet by Cowork.&lt;/p&gt;
&lt;p&gt;It was fun, interesting, and ended up being a lot more work than I had expected. I would say that I benefitted immensely from having AI as a collaborator on both the thinking and the tedium of this exercise. AI is not always or even often right, but by having it give me something to edit and start from, it has made it easier to keep making progress. Without AI, I wouldn’t have been able to achieve the amount of rigor, and frankly just spend the amount of time and effort on a project like this.&lt;/p&gt;
&lt;p&gt;So was my friend right about being behind? Depends on who he compares himself against. Yes if it’s against the bleeding edge of AI adoption. And an empathetic no, because managing humans is not something AI is good at.&lt;/p&gt;</content:encoded><category>writing</category></item></channel></rss>