Show HN: Turri – a coding agent with the power of regenerative software
github.comCoding agents let me move fast. To keep up, I stopped reading the code, and with it I stopped understanding my own software. I lost my sense of engineering along with it. I was still the one accountable for software I didn't understand. No workflow or better model fixed that, so I built turri.
turri is based on Pi and the concept of regenerative software introduced by Chad Fowler. The ability to regenerate the same piece of code multiple times and always get the same results in terms of functionality is called the deletion test and proves that your coding agent completely understands you. The idea is that every time part of the software needs to be changed, you regenerate a new version of the code based on the durable information you have about the system.
The durable system information includes specs, tests, ADRs, and other types of documents, and it is written in ***plain. You write these with the help of an agent, and Turri starts partial regeneration of the software you're changing. You can repeat this process as many times as you want until you're happy with the change you're implementing. The regeneration also includes proofs that the generated code completely conforms to the system knowledge on which it was based (it implements all the tests that are part of the definition and automatically adds additional tests).
You can try this by cloning the repo or by installing it from my landing page. I created a desktop app to improve usability. Currently, it's only suitable for new projects, but I'm working on adding support for existing projects.
I also wrote the full story in case you're interested: https://turri.dev/blog/why-i-built-turri/
How does regeneration deal with persistent state? If a **plain change leads to a different DB schema, does turri generate migrations, or is the data layer treated as something that can’t just be thrown away? This has been the hardest part for me with spec-first generation.
Yes, turri will generate migrations with every change, so if you need to deploy a new version it will check against the current schema and generate it properly.
Honestly, I haven't used it on some reasonable scale to fell the real issues of migrations yet. I consider this to be one of the biggest problems with the approach, but I think it's addressable.
How do you approach this problem?
I went the other way: I do not generate code from scratch. In my workflow, the specification sis the source of truth. Every change goes in as a change request that becomes new tasks in the plan. Instead of recreating code, the agent modifies existing code. Migrations are strictly additive. Every schema change results in a new file, leaving previous files untouched. Each migration is backward-compatible. Destructive operations, such as DROP commands, are isolated into a separate, subsequent phase that I personally review.
The largest project I’ve managed this way has been in production for about six months and has already gone through 45 versions. So far I haven't had encountered no no data loss so far”.
Renaming is where I would be wary of generating code from scratch. Based solely on a schema diff, a rename appears as the deletion of one element followed by the addition of a new one. Does turri ask about what you meant in such cases, or is there a way to specify this directly within the specification?
Check Chad Fowler's The Phoenix architecture series for more information on regenerative software: https://chadfowler.com/regenerative-software/
How do you enforce the deletion check? I understand that it is important to make sure the regeneration can be trusted but do I really need that?
I consider this to be the most important concept of the regenerative software approach. Basically, if you can regenerate a certain module multiple times you are certain that you nailed down every detail that are describes that module.
If this is true, it means that each new change in the system can be reliably described with a small change in the system knowledge (usually it includes some small update in specs and tests) and regenerate with very high certainty that the produced code will be correct.
Basically, the regeneration test is putting a solid ground for all future improvements.
Ok, that makes a lot of sense. But how do you do it in practice? How do you test if the spec passes the deletion check?
Through multiple steps I would say.
First, it automatically confirms that all defined tests are passing but it's hard to say if the defined tests are covering all the edge cases that are important.
It will also write a bunch of mutation tests and do the automatic tests based on the type of application.
At the end, you would still need to manually check to confirm the functionality (unless until you are confirming inital deletion test for a certain module).
I was expecting it to generate the application twice and then do automatic testing side by side to confirm it works the same, or something like that.
Does it do anything similar?
Really interesting idea. We need more tools like this to see if regenerative software actually works in practice. Nice to see someone trying it.
While building turri, I build quite some internal tools that I'm still using. I'm planning to open-source some of them.
Please, try it yourself and let me know what you think.