In the last post I argued that when AI writes code, the contracts between features tend to break down everywhere at once, because nothing carries them from one session to the next. To answer "how should that carrier be organized", I have to go back to a more basic starting point that usually gets skipped: why does project management need documentation at all? If I can't answer why, I can't answer how.
Conventional wisdom reduces the value of documentation to three things: it brings everyone involved to a shared understanding (so nobody's memory of a meeting drifts), it guides later development (it is the basis for requirements and interfaces, and it settles the technical approach), and it serves as evidence for future decisions (even the author forgets why a library was chosen three months later). Those three define the baseline property of documentation: it has to cover who needs to know what, not just who is responsible for writing what.
But the traditional horizontal split by job function is organized around precisely that: who is responsible for writing what.
How Horizontal Layering Fails, and the Pain of Duplication
In the traditional setup, requirements belong to product, architecture to the architect, interfaces to developers, black-box and white-box cases to QA, and final sign-off to some manager whose role is anyone's guess. This assumes something: that somewhere in the process sits a Mr. Key who holds the complete context and can connect the documents to one another. Once AI enters the process, the execution boundaries between roles start to dissolve. AI is not one link in the chain; it is in every link.
Faced with that shift, horizontal layering reveals a fatal structural flaw: the context around one matter gets scattered, so duplication means inconsistency.
Here is a real case from our own work. The interface encryption policy applies to every module. Under the traditional horizontal system, every module's interface document reproduced the encryption method and the key-fetch logic. Encryption and decryption as interface behaviour can reasonably be declared inside each module. But key management is a global policy, and it should have exactly one authoritative source. When the security policy changed, the owners of three modules each updated their own document, and they ended up with three versions that contradicted each other — one of them even had the public and private keys deployed in the wrong places. Then AI, generating code for a new module, dutifully read one of the wrong documents, and the output came out in direct conflict with the global security policy.
This is not carelessness. It is a mismatch at the organizational level: the global contract called key management has no single physical location of its own in a horizontal split. Set a few contradictory documents in front of someone and even a senior engineer has to guess; AI has no basis at all for deciding which one is authoritative.
Vertical Modularity and Progressive Disclosure
If both people and AI are to read contracts precisely, the main axis cannot be the horizontal cut by document type (requirements / design / test). It has to change to vertical modular organization by layer.
Project level (shared at the top): this is where global contracts are gathered. Project background, technology stack choices, user persona analysis. Global security constraints like key management, and the standards for how modules connect to one another, all live here, and only here, in a single copy. Change it once and everything is bound by it.
Module level (owning the boundary): this defines what a module does and what it does not. Which capabilities it offers outward, which external capabilities it depends on, how its core domain model (DDD) is designed — all of that is settled at this level. It does not supply the implementation, but it is the principle the implementation follows.
Feature level (behaviour spec): this focuses on the concrete logic of a single feature. How the feature is triggered, how it handles exceptions, and what its tests and acceptance scenarios are.
Why vertical modularity rather than horizontal layering? Because horizontal layering leaves one feature's context scattered across repositories or folders that sit far apart, and AI cannot load even a minimal complete context. Vertical organization means everything known about a feature — design, decisions, tests — sits in one slice; that slice can be traced upward precisely and inherits the constraints set at the module and project levels. That is far friendlier to AI.
Take our message bus module, where we decided to adopt the Gossip protocol as the mechanism for syncing cluster data. In the vertical structure we designed, the reasoning behind that decision is completely clear: the Gossip protocol at the feature level → the decentralized architecture at the module level → the project-level requirement to withstand a single point of failure. The decision was derived top-down, so tracing it reconstructs it bottom-up. If AI, working on something similar, can read the requirement at the top level, it will not overstep and produce a centralized design that violates the principle.
Constraints Have to Be Hard Rules
Vertical layering settles where a contract lives and how far it reaches. But a contract having a definite place does not mean it will be followed faithfully.
Human code review has a hard physical ceiling. Given a hundred constraints, a reviewer remembering eighty is already the limit. When AI can turn out the code for twenty features in an afternoon, the line human review holds is bound to collapse.
So the central judgement of this whole system is: every hard constraint that must be obeyed has to be mechanically traceable to a specific test. It can never fall back on human review.
If a constraint — "no use of a certain feature at the platform layer", for instance — cannot be turned into an automated check or a test assertion in the pipeline, then it is just a worthless sentence. Layering logic solves whether a contract can be located; test traceability solves whether it can be executed. Neither works without the other.
Of course, this system has an honest boundary: it only governs the agreements that got written down. Which agreements count as hard constraints, and which level each of them belongs on, still takes an engineer's experience to judge and define. A tool can backstop execution. It cannot backstop technical judgement.
This post has been about choosing the dimension to reorganize documentation along, and the layering logic behind that choice. How the idea actually lands in engineering is something you can explore on your own. Next time I will write about how this methodology on paper turned into a dedicated tool I designed while iterating from v0, and the problems I ran into along the way.
Top comments (2)
the three contradicting copies of the key management policy is a good example of how copied docs drift. do you keep the project level one as the only source and have module docs just link to it, or does each layer restate the parts it depends on. restating is where the copies start diverging again. im building docup, its about generating docs from the repo instead of copying them by hand
Good catch — that's exactly the failure mode. In our setup the project level is the
single source: key management lives there once, and module docs link to it instead of
restating it. Restating is where copies start to diverge again, as you said.
What each layer does own is its own constraints — a module doc states which
capabilities it exposes and which it depends on, not what the encryption policy is.
The link upward is a reference, not a copy.
That's also what keeps the chain traceable: feature → module → project is a set of
links, so changing the top layer propagates without touching the ones below.
docup sounds like the right direction for the generation side — from what I've seen,
the hard part is usually deciding what the single source should be, not producing
the file.