Working with AI

comma_at2 pts0 comments

htmx ~ Working With AI: A Concrete Example

Working With AI: A Concrete Example

Carson Gross<br>June 29, 2026

I am, generally, ambivalent towards AI. There is no doubt has become a very powerful tool for development in the<br>last year, but it also comes with many dangers, both<br>for us individually (e.g. the slow dulling of our intellects) as well as collectively (e.g. environmental concerns,<br>increasingly expensive personal computing, etc.)

In “Code is Cheap(er)”, I warn about The Sorcerer’s Apprentice problem, where a developer becomes reliant on AI and is unable to<br>understand and properly address issues that come up in the systems they are building.

In this article I want to go through a specific interaction that I had with AI while maintaining<br>hyperscript to show the strengths and weaknesses of AI in general and to demonstrate<br>The Sorcerer’s Apprentice problem (which I narrowly avoided) in particular.

The Hyperscript Parser

For some background, hyperscript is an alternative interpreted scripting language for the web. It is, ironically,<br>written entirely in JavaScript.

It is a strange piece of software: I intentionally broke many of the rules of parsing when writing it as an experiment<br>to see how things would work out.

Some examples:

Parsing logic is colocated on parse elements

The parser is pluggable, and the grammar is defined dynamically

It supports multiple syntaxes for property access.

It is not an approach I would recommend for most programming languages, but it has worked out pretty well for this<br>project.

Yet another demonstration that there are indeed multiple ways to skin the cat in software.

A Bug Report

Our story begins when a user reported a regression when upgrading to the 0.9.91 release. The following<br>expression no longer parsed properly:

fetch `{% url 'trade:get_symbol_data' %}?symbol=${symbol}` as JSON

In particular, the as JSON was binding too tightly and trying to convert the string literal into JSON before it<br>was handed to fetch instead of doing what the user expected (and what it did previously) namely fetching the<br>given url with the results treated as JSON.

This sort of binding conflict is a classic problem in parsing.

Because hyperscript is an xTalk style language and<br>inherits many of the ambiguities of English, this problem is all the worse in it.

Investigating The Cause

The first thing to do was to investigate why this regression occurred.

This is an area where I am typically going to lean on AI to help.

I use Claude, and it did an admirable job finding the root cause: in 0.9.91 I had been overly<br>aggressive in refactoring the go command to reuse/share logic with the fetch command.

I had extracted a common method for both of these commands to use, parseURLOrExpression(), but, in doing so, I<br>accidentally expanded the grammar after the fetch command to include the general expression, er, expression.

The as keyword has a meaning in expressions: it is a conversion expression,<br>allowing you to convert between types:

set x to "42" as Int

But the as keyword is also a modifier of the fetch command, telling it how to convert the response:

fetch https://hyperscript.org as Text

(Perhaps this fact makes you throw up a little bit in your mouth. Good.)

The crux of the issue was that, inadvertently in the refactor, I had made the parser parse an expression after a fetch keyword<br>which was now consuming the as keyword as an expression, rather than allowing it to be a modifier for fetch.

With the help of Claude I was able to figure this out in a few minutes, much faster than if I had had to<br>figure it out on my own.

Fixing The Issue

AI was very helpful in finding the cause of the problem.

In fixing the problem, however, it was much weaker.

I will admit here I was being lazy and asked AI for a solution, so complaining about those solutions feels a bit, well,<br>lazy, but I still think the string of events is informative, so let’s go through exactly what happened.

Proposed Fix 1: A Hack

The first suggestion that was given was to parse what is called a “string-like” leaf first,<br>then fall back to a full expression:

return this.parseElement("stringLike") || this.requireElement("expression");

This fix would have solved the immediate problem presented by the user.

However, it was very specific to the reported bug and wouldn’t have fixed the general case, such as if someone uses a variable as the target of a fetch:

fetch $url as JSON

I rejected this proposal because of this: too hacky and not general enough.

(Note that the hyperscript parser has plenty of organically supplied hacks in it, so this may have been the pot calling the<br>kettle black.)

Proposed Fix 2: Better But Unnecessary Complexity

The second proposal was more interesting: add a noConversions flag on the parser, set it around the URL parse, and have<br>AsExpression.parse bail when it is set:

// AsExpression.parse()<br>if (parser.noConversions) return;

This will horrify many parser engineers because it makes the...

fetch expression problem parser hyperscript parse

Related Articles