Refactoring through our 123rd ADR
ADR stands for Architecture Decision Record. It's a critical aspect of producing well-design code using GenAI (in my case I use Claude Code). The idea of an ADR is to capture something platform-sized. Something that improves the overall code base and developer and author experience when eventually someone besides myself might want to build a story using Sharpee.
In the latest batch of these documents we discovered a need for action interceptors, though the IF community knows these as Before, Instead, and After. Sharpee didn't know about them until yesterday.
I go through and read the code regularly and if I see something fishy, I investigate. We had about 30 handlers for the Dungeon port and I smelled a rat. We looked at the patterns of these handlers and realized all but about 5 could be normalized into types of orchestrations. This includes formalizing what a Daemon is, added a declarative state machine, and migrating most of those 30 handlers to proper domain-oriented implementations. We also had an NPC implementation that was ad-hoc and we formalized that. In order to accommodate these new things, we built a plugin system so they get registered by the story when they're needed.
In a parallel session (I get bored watching Claude work, so I have Claude do other things in another terminal window) I asked Claude if we'd designed the system properly for separation of church and state. By this I meant, could we build a story runner and then package a story separately, The idea of anyone building an Electron or Tauri app seemed like asking too much. We'd already built a functional React app, so we moved it to package/zifmia (stolen from my client-server fyrevm days) and designed a stand-alone browser-based Sharpee story runner. this also let do making sure we were serializing everything (we were not) and designing what a story file is (zipped JavaScript with encrypted text so no cheating). The first story file produced is dungeo.sharpee and it's 172kb.
And of course we want to enable images and author-directed styling, so we enabled those as well. The author can tag any text with an image, location, border, and size, and Sharpee will unknowingly emit a second domain event with that information. The text service will see two events, the normal one and the styling one, and handle them accordingly. If the client is bare-bones, the styling is ignored. The author can also add assets like a global CSS style sheet.
As for the port of Dungeon, that's mostly done outside of walkthrough testing and we're currently through 7 sections of the game (torch/bank/maze/Egyptian room/exorcism/frigid river and rainbow). These walkthroughs have remained stable through every regression of the changes listed above.
I nearly asked Claude to over-engineer some of the daemons from Dungeon, but we pulled those back. They were fine readable code, but produced no benefit. Outside of that, Sharpee continues to march forward to a very near future 1.0 release.
I encourage people to look through the repo at https://github.com/chicagodave/sharpee/ and submit issues or feature requests or just visit https://sharpee.net/ though the site is slightly out of date. I'll update it when we finish this last bit of zifmia work and I update the npm packages.
One request I'd like to implement is alternate language file/parser pairs. Might require some pair programming with someone savvy, but I don't think that would be a ton of work.