I first started working on DAViCal in around 2004. My original motivation was some years of frustration regarding shared calendaring choices available to Linux users, combined with my experience working with Windows 2.x in the early '90s and the (very basic, but working) was I could create meetings and invite other people to them, let others view my calendar, and so forth. That was from my time wotking at Inland Revenue in New Zealand.

While I'd worked on "free software" in the '80s, it wasn't a "movement" then - it was just something one did: "You like my tools for Pick? Oh, here, have a copy!" - but in the mid '90s I started booting Linux from floppies, and eventually CDs, and when we started Catalyst in 1997 I decided I was going to start using Linux full time on my laptop.

A Wild CalDAV Appears!

Many things changed from 1997 through to 2005 but calendaring just did not seem important to free software teams - not visibly anyway. Since about 2003 I'd been watching the development of the CalDAV standard by Cyrus Daboo, Bernard Desruisseaux and others with interest, and as it approached ratification I decided to start work on a client.

When one has a hammer, of course, everything looks like a nail. My language of choice in the early 2000's was PHP - it had provided me an easy enough transition from writing Progress 4GL in the '90s to writing code for the web, though my extensive prior background with top notch databases like Progress meant I wasn't going to settle for MySQL and looked instead to it's less popular but more capable PostgreSQL.

Through the 2000's then I was increasingly involved in improving DAViCal, attending a number of the Calendarying and Scheduling Consortium's "CalConnect" meetings and getting to meet the people behind those standards, and - perhaps more importantly - attending the associated interoperability events where we would all bring our clients and servers and attempt to get them to interoperate.

As a part of that interoperability, I built an extensive regression test infrastructure alongside DAViCal where I could hit it with all sorts of in- and out-of- spec requests copied from a wide variety of CalDAV clients.

I stopped working on DAViCal back in 2012 when Heather was diagnosed with Breast Cancer, and evern after her rcovery I was very distracted by my new role with OLPC, and then with Google, and moving to Ireland. DAViCal still exists, however - "community maintained" by a small but dedicated group of people who really don't have enough time on their hands, but it's really starting to look very old in comparison with a modern stack.

So in the intervening 15 years I've had quite a bit of experience writing in Go, and I've decided it's time to rewrite DAViCal, using my current "hammer". The other tool in my toolbox these days is LLM-based coding, and this - combined with those regression tests - is what really makes this an achievable goal for me.

The Approach

Starting with the DAViCal PHP code, I asked the LLM to write me a plan for how to build the same thing in Go.

A couple of days later I had something that seemed to have an implementation of basic CalDAV feature set, so it was time to teach it about regression tests...

The first thing I told it todo was to use the existing test format, but rewrite the test runner in Go, to give us greater flexibility than the super-complex shell scripts used (with Curl) to run through the tests in the original PHP code base.

After we got through the first 4 tests this flexibility started to show dividends, and some differences were resolved with additional result normalisation steps - easy to build in Go.

After getting 8 tests to pass it started to become clear that rerunning tests was going to be a big thing since many of the tests reflect a series of steps that a CalDAV client might take: reading a calendar, modifying an event, requesting a report,... So I asked the LLM to add new 'CHECKPOINT' functionality to the tests, and to be able to identify which tests were data-modifying, so running from (e.g.) test 35 might involve restoring to the checkpoint for test 30 and then running test 32 and 34 before hitting the test we want.

Interestingly the LLM was getting the hang of the job at this point, and would run for easily an hour or two just fixing one test at a time, with me occasionally guiding the way it resolves issues - it has a tendency to go for the easy fix rather than the correct one. I've been able to reduce that tendency somewhat by explaining that many people are going to look at the code once it's done and it should write something it can be proud of! Well, it helps, but it doesn't always work.

Code review is ongoing. It writes pretty decent code when it's let loose. It writes excellent comments to, in line (or exceeding) the Go guidelines: not too verbose, but with good information when needed.

Riding the Bull

Keeping an eye on the LLM I found that the best approach was to (regularly) tell it to stop after "fixing" a test and wait for me to review the work. This is working well: it regularly resolves the issues with a test and produces a fixed version, or - in some cases - arrives in a situation where the way that PHP DAViCal did things was (or is) wrong now.

When we've worked through one issue and are ready to look at the next, I can often offer useful guidance about the next issue, pointing out which RFC applies and so forth. Usually after a conversation compaction it will forget that it's supposed to stop, and will continue for a few tests until I notice and rewind some possibly bad decisions.

We're getting there though. At this point 176 of the regression tests are passing, and I think by the end of March I'll have something usable on a small scale, and perhaps by the end of April something that can be used in place of the PHP version.