Zum Inhalt springen

Requirements at a glance

Why requirements live next to the code, what the tool checks about them and what it does not, who on the team gets what out of it, and how a requirement moves from its first line to acceptance.

This page explains what the requirements in CodeCharter are good for and what they feel like day to day. The file format with all fields comes after that, under Requirements.

The problem

The requirements for a product almost always live somewhere other than the code that implements them: in a specification document, in Confluence, in Jira tickets, in the minutes of a workshop. On the day of sign-off, both sides match. After that, the code keeps evolving, and the link between the promise and the place in the code that fulfills it survives only in the memory of the people involved.

This shows up in three places. At acceptance, someone has to manually piece together which promise is fulfilled where. At an audit or a certification, the same evidence gets demanded again, this time in writing. And six months later, someone changes a method without knowing that a contractually promised property depends on it.

The approach

In CodeCharter, a requirement is a file in the repository, right next to the code. It is reviewed in the same pull request, inspected with the same git blame, and travels with the same branch. An anchor in this file names the place in the code that fulfills the requirement, and the command codecharter req check reports when the file and the code no longer match.

What matters here is what the tool claims and what it does not. CodeCharter does not decide whether your code substantively satisfies a requirement. It records that you claimed it does, who accepted it and when, and what evidence that acceptance rested on, and it reports as soon as that evidence no longer holds.

Concretely, the tool checks the structure of the corpus, that is duplicate ids, references pointing into the void, criteria without a usable carrier, and the contradiction of carrying a requirement as implemented while its own acceptance check is still open. With --with-code it additionally checks whether the anchored symbols still exist at all and whether an acceptance that was once pinned still matches the code. What it does not check is the content: whether the requirement's text describes the right thing and whether the bound test tests the right thing remains human judgment. That is exactly why acceptance via codecharter req accept is deliberately not an MCP tool — an agent can prepare everything, but it can accept nothing.

Who on the team gets what out of it

Developers see, when changing a method, whether a promised property depends on it. The MCP tool req_context answers exactly this question for a symbol, without anyone having to search a specification document.

Reviewers get the requirement change in the same diff as the code change. A new [Satisfies] attribute lands as a line in the diff and is read there like any other code change.

Project leads and clients have, with documents.yml, an outline over the corpus from which a specification document, a requirements document, or an acceptance protocol can be assembled, and, with the rollup per requirement, a statement of what currently holds and what does not.

Auditors and QA do not read the code, they read the acceptances: who approved which criterion when, on what evidence, and whether that evidence still holds today. All of that is stored, versioned, in the repository.

AI coding agents read the same corpus through ten MCP tools, instead of parsing the files themselves. They may research, draft, bind, and ask for approval, but they cannot accept anything.

The lifecycle of a requirement

The following example follows a single requirement through every stage. It is the same one that reappears on the following pages.

1. The promise is made. In a workshop with the client, the sentence falls that users must be able to reset their own password. Until now, this would have been one line in the minutes.

2. The promise gets a file. Under .codecharter/req, REQ-12.req.md is created with an id, title, priority, and a statement of whether the promise is contractually binding. The prose in the body is what a reviewer or auditor later reads to understand the why.

3. The promise becomes checkable. A requirement that nobody can verify is a statement of intent. So it gets criteria, and each criterion states, through its carrier, how it is verified: by a rule, by a named test, by a manual step, by an integration suite, or by something outside the repository.

4. The promise is bound to code. An anchor names the symbol that fulfills the requirement, or expects a [Satisfies("REQ-12")] from the CodeCharter.Annotations package on the implementing member. Without an anchor, the check rejects the status implemented with an error.

5. The promise is checked continuously. codecharter req check runs in CI without a solution and without the .NET SDK, and is therefore fast enough for every pull request. With --with-code, the check against the analyzed code model is added.

6. The promise is accepted. A human runs codecharter req accept REQ-12 AC-1 --by <name>. This pins the approver, the date, and the evidence the approval rests on into the file.

7. The promise survives changes. If the accepted test or the anchored code region changes, the pin no longer matches, and the requirement renders as Stale instead of silently continuing to count as satisfied. The acceptance is then deliberately repeated.

8. The state becomes measurable. codecharter req coverage answers both directions: does the evidence for each requirement still hold, and which code carries no justification at all. Details under Requirements coverage.

Do we need this?

The effort pays off if at least one of these points applies to you: you work against a specification document or a fixed price, someone external formally accepts your delivery, you have to prove to an auditor where a property is implemented, or you let AI agents work on a codebase where certain promises must not break.

The effort tends not to pay off if you are building an internal product without formal acceptance, your requirements arise as tickets anyway and are done once merged, and nobody later demands proof. What speaks against the tool in that case is described in detail under Scope and effort.

Next steps