Software Engineering Is Not Prose
AI today mostly gets Markdown and prose. But software engineering is a mesh of terms, requirements, and tests that hang together. A look at Google's Open Knowledge Format, SKOS, and arknet, a tool taking shape.
My first day at work was in the summer of 1999. Together with the head of department, I carried a desk into his office. As we were carrying it, he said: “The C++ project’s already been assigned. But I’ve got a Java project where you could help out.” I didn’t know a thing about Java. His advice: “Get yourself a book, spend two weeks getting to grips with it, then we’ll get started.”
That’s how I learnt Java. Nothing like that had come up during my training; I’d learnt C, PLC and assembly language, followed by C++ during a longer work placement. Process models, requirements engineering, software architecture – those things simply didn’t exist in my world up to that point. The approaches certainly already existed in 1999, just not where I was at the time. I had no process. I had a book and two weeks.
What came next wasn’t a single moment when everything clicked. It was twenty years of small nuggets of inspiration. Reading. Talking to people. Workshops. Projects where something went wrong, and I understood why afterwards. In the end, it wasn’t just about more knowledge. It was about connectedness: seeing a detail in a project and knowing which ten other things it’s connected to.
That’s exactly where I see the gap in AI today. Not in knowledge – it has plenty of that. What it lacks are artefacts that carry this connection themselves, so that it can understand a decision.
The thesis illustrated with a real-life example
These days, AI mainly deals with Markdown files. Agents receive vast quantities of them, in every form, for everything: READMEs, ADRs, onboarding documents, summaries, notes. However, software engineering is not prose, but a network: a term is linked to a requirement, a requirement to a test, and a test to what actually happens in the end. Even a summary in Markdown may alleviate or exacerbate the problem, but it does not solve it.
On 12 June 2026, Google published a format for this: Open Knowledge Format, OKF. In it, Markdown files become ‘Concepts’, linked via standard Markdown links to a knowledge graph. I think this is a step in the right direction; linked is better than isolated. However, the links are untyped. They state that two things are related, but not how. Six weeks later, on 25 July, version 0.2 was already released, now with fields for trust and provenance. This does not change the actual issue: the links themselves remain unnamed. So OKF, too, comes up against the limitation we’re discussing here.
The problem persists when you look for it where artefacts for AI agents are currently at their most structured: in spec-driven development, using tools such as GitHub Spec Kit or AWS Kiro, which automatically derive plans and tasks from a specification. Even there, the spec, plan and tasks are linked only via file paths, section headings or execution order, not via named domain-specific relationships. Kiro goes the furthest: tasks even know which task is waiting for which. But that is an execution order, not a statement about how two concepts are related in the domain.
And what if a specification changes? Spec Kit has a command for this that reads the specification, plan and tasks through completely once more and checks for inconsistencies. However, this is again a prose run-through by a language model, not a check against a structure. A second hallucination can just as easily overlook a first one as it can confirm it. The only way to establish a hard fact here is through executable tests, but these check behaviour, not whether a claimed relationship between two concepts is actually correct.
I’ve been doing what OKF is trying to do for quite some time now, just not using a brand-new format. I use SKOS, a seventeen-year-old W3C vocabulary for concept hierarchies, for the folder structure of one of my own projects. Each folder has a README with a few fields: what it means, what doesn’t belong in it, and how it relates to other folders – three different relationships: one level higher, one level lower, or on the same level and related. No tool, no library, just a convention that I stick to – and which only holds if someone, myself or an AI, also knows the SKOS meanings of ‘broader’ and ‘narrower’.
This is precisely where the difference lies compared to OKF and spec-driven development. A Markdown link says ‘this is somehow related’. A named relation says how: the relation has a name, and that name is part of the information.
A real-life example from a small online shop that I set up as a test case illustrates what this means in practice. Two terms: once an ‘Order’ has been created, it is immutable; it can only be cancelled, never edited. A ‘Payment Authorisation’ precedes the order and expires if the order is not placed in time. The relationship between the two is itself named – “precedes” – not just a link that merely asserts that something is connected. A requirement uses both terms, with three acceptance criteria: if authorisation is declined, no order is created; without full authorisation, no order is created; and the authorised amount must correspond exactly to the order value – never partially.
Write that as a prose sentence: “Payment must be verified before the order is placed.” It sounds the same. But it’s empty. What happens if it’s rejected? What about partial amounts? Can the order still be amended afterwards? It is precisely these facts that are lost in prose form, every time someone, whether human or AI, reads the sentence and has to reinterpret it. If necessary, this could be written down more precisely in plain prose. What is still lost, however, is the traceability: if ‘Payment Authorisation’ changes, there is nowhere stating which requirements and use cases are affected; this has to be looked up manually. With a named relationship, it’s a single query.
When nothing is connected
It is not enough for the wording to be correct if the result is not connected to anything. A requirements engineer at a telecoms provider delivered exactly that: requirements, page after page, linguistically sound, following the template. Nevertheless, we couldn’t make head nor tail of them because they lacked the terms to which they referred, and the use cases that should have contextualised them. Like methods without classes.
This is the extreme case of the point made above: not merely an unnamed link between a requirement and a term, but no link at all. Without a link, precise language is of no use, no matter how print-ready it sounds. It’s exactly the same with AI: it can only access what is actually linked, whether named or not. Scattered documents remain scattered, no matter how precise each one is in its own right.
arknet: The experiment
I’m currently developing such a tool myself: arknet (github.com/kogn-io/arknet, discussions at …/discussions). It records terms, requirements and use cases as verified facts with named relationships, as the Order/Payment example above illustrates. More recently, it has also started to include architectural decisions: recorded with context and alternatives, and referenceable just like any other fact in the graph, rather than as a mere assertion floating in the air. I am currently testing for myself whether this holds up in day-to-day project work.
I’m deliberately not saying that arknet proves the thesis. It’s an attempt to substantiate it – a tool that’s only just emerging, not a finished product. But it’s the most honest test case I know of: either it actually helps, because the connection matters, or it doesn’t, and in that case the thesis was wrong or too simplistic.
AI will increasingly build simple applications without much guidance, and that will work. When it comes to complex projects, what separates Vibe Coding from AI-assisted development is not whether an AI is involved, but whether the connections between the artefacts are preserved. Without that, even a complex project will be completed, but it won’t be maintainable – a disposable prototype in production: it works today, but no one, not even AI, will be able to say with any certainty tomorrow what will change if a single term changes.
An example of this is closer than it sounds. Take ‘Order’ and ‘Payment Authorisation’ from above once more. Tomorrow, an agent might claim that the two are now linked differently, that the sequence has changed. In a world of Markdown files, the only way to assess this is for someone to read the text again – be it a human or AI – with the same uncertainty as the first time. In a world with named, typed relationships, this is a simple check: does the new claim fit the schema, yes or no – that shows whether it’s admissible, not whether it’s true.
Ultimately, the difference between a claim and a fact is not how convincing it sounds. It is whether it can be verified.
If you see it differently: by all means.