AI Engineer Europe 2026
BDD, ADR, PRD, WTF: Capturing Decisions for Humans and AI Alike — Michal Cichra, Safe Intelligence
Read the talk
Capturing Decisions That Humans and Agents Can Recover
Decision records, executable scenarios, reusable UI patterns, and automated checks preserve the reasons behind a product when people forget and agent context disappears.
From a talk by Michal Cichra
Before you start: Familiarity with Git, automated tests, and database-backed applications will help with the examples.
Why do we still have this rule?
Why does a product keep a flow, a feature, or an architectural rule after everyone has forgotten its purpose? Michal Cichra approaches that problem from experience at Microsoft, Red Hat, and a decade spent on one product. At Safe Intelligence, his team had just released an agent-testing product. The consistency problems surrounding AI were familiar: teams already struggled to preserve the reasons behind their decisions.
Consider the five-monkeys ladder story that opens his explanation. Monkeys are punished with cold water when one tries to reach bananas; eventually, they stop one another from climbing. Replace the monkeys one by one, and the prohibition persists even after none of those present experienced the original punishment. Cichra explicitly questions whether the story is an urban legend. Its value here is as an analogy: a rule can survive long after its rationale disappears.
Humans forget, and humans leave. LLM context gets compacted, and an agent cannot depend on durable memory of earlier work. Eventually someone asks why a flow exists, what problem a feature solves, why the code has a particular shape, or where a change belongs. The founding engineer may no longer be available to explain. AI can make this familiar organizational problem arrive sooner. The rationale needs to remain recoverable outside the person or session that produced it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Record the architectural reason and the enforcement path
An Architecture Decision Record, or ADR, records why a technical choice exists and how the team intends to enforce it. References and code examples make the decision actionable. The document should explain more than the rule itself: someone encountering the constraint needs enough context to make a correct change.
Cichra’s example is a layered architecture intended to prevent N+1 database queries. Import linting restricts which modules may depend on which others. Database reads return plain data shapes rather than ORM objects, so downstream code does not receive objects that can issue additional queries implicitly. The boundary controls both where database access happens and what crosses into the rest of the application; he also connects these constraints with avoiding duplication. He describes roughly fifty other ADRs defining the product’s architecture.
There is no mandatory ADR format. A text document can explain a decision, but it cannot enforce that decision on its own. A separate tool must detect the violation and provide useful feedback: which rule was broken, why the rule exists, and how to fix the problem. The agent can then retrieve the ADR for details. Recording the relevant files, folders, or language scope helps connect a failure to the code and decision it concerns.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep the product purpose lightweight
A Product Requirements Document, or PRD, preserves a different kind of intent: why a feature exists, which problem it solves, and how the user moves through the application to use it. It can be short. The useful connection is between the problem, the desired outcome, and the journey that takes the user from one to the other. An exhaustive document is not required to retain that connection.
This is useful for an agent implementing the feature, but it is equally useful for the person returning to it six weeks later. The document makes the original purpose available when memory no longer does.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make the behavior specification executable
A written specification leaves a validation question open: how do you know the running product behaves as described? Markdown captures intended behavior, but does not test conformance. Reviewing generated tests is not necessarily a comfortable substitute; Cichra finds AI-written tests even harder to read than AI-written code. Behavior-Driven Development, or BDD, supplies an intermediate layer that describes behavior in language a person can review.
Cucumber makes that layer executable. Scenarios can connect directly to PRDs and critical user journeys. Their steps map to code that exercises the application and checks the result. This connects the readable specification to an actual validation path rather than leaving it as a description beside the implementation.
For example, a profile-saving journey can express the initial state, the action, and the expected persistence without exposing test plumbing:
gherkin
Feature: Save a profile name
Scenario: A saved name survives reopening the profile
Given I am signed in
And I am on my profile page
When I change my display name to "Mira"
And I save my profile
And I reopen my profile page
Then my display name should be "Mira"
Each step needs an executable implementation; the scenario alone does not perform the test. Its wording gives reviewers a clear behavioral contract to inspect before they examine the code behind it.
The scenario vocabulary belongs to the team. Different formulations can describe the same journey, provided people can read, review, and understand what the application is expected to do. Scenarios can also refer back to the documents explaining why that behavior exists. The result is a connection between product purpose, expected behavior, and executable checks.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give agents a visual vocabulary they can reuse
Consistent interfaces need the same treatment. A design system and pattern library provide the shared vocabulary that made UI work consistent before agents were involved. Start with a concrete definition: a primary button is blue, with a specified shape and size. Then define its usage rule—for example, only one primary button should be visible on a page at any point in time. Appearance and usage are separate decisions, and both need to be explicit.
Components turn those decisions into reusable pieces. Document their colors, variants, and states, then provide previews and snippets that let humans and agents inspect them. Review the previews against the visual principles before reusing the components. As with code, build larger patterns by composing smaller pieces; otherwise each new screen becomes another opportunity to invent a competing convention.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Put feedback on the path to a pull request
Documents and reusable components still leave an operational question: how do people and agents keep following them? Cichra’s answer is a repeating work-and-feedback loop. His team’s harness combines Git hooks, skills, CI, linters, and other checks. An agent tasked with delivering a pull request must interact with Git, which provides a natural place to trigger feedback.
Hooks run predefined tasks locally, and CI runs the same tasks remotely. That duplication matters: local hooks can be bypassed, including with --no-verify, so hooks alone do not make checks unavoidable. Repeating the checks in CI catches changes that skipped local validation. The checks cover linting, formatting, type checking, code duplication, architectural boundaries, and document linting.
Automate mechanical rules so review can concentrate on higher-level decisions. Tabs, spaces, formatting, and other settled conventions do not need to be renegotiated in each code review. Encoding them as checks gives contributors consistent feedback and leaves reviewers more attention for design, behavior, and architectural consequences.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Prevent forbidden dependencies, then explain the repair
Architecture checks make abstract layering rules concrete by controlling module imports. In Cichra’s end-to-end BDD suite, tests cannot access the database or import modules capable of accessing it. That restriction forces the suite to exercise the application through browser behavior instead of reaching behind the interface to manipulate or inspect database state.
The product applies a related boundary: rendering templates cannot talk to the database. Together with returning plain data rather than ORM objects, this removes a route by which rendering can trigger an additional query for each item. Cichra describes his architecture as preventing N+1 queries entirely; the generalizable mechanism is narrower—preventing database access from rendering blocks that class of implicit query, rather than proving every database path is free of N+1 behavior. The aim is to make an unwanted dependency impossible instead of repeatedly finding its consequences in review.
The feedback loop then has a concrete repair path:
- The agent attempts to commit or push a change.
- A check detects a violation and rejects the attempt.
- The failure links to the relevant decision document.
- The agent reads the rationale, corrects the change, and tries again.
A rejection becomes useful when it points to the information needed to resolve it. The durable document restores context at the moment the agent needs it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep the loop, change its focus
The cycle of doing work, receiving feedback, and revising stays the same across product features, UI work, and backend changes. What changes is the information and feedback most useful for the current task. Skills supply that focus.
- ADR and PRD work: An ADR skill guides the agent to decision records and the code they affect. PRD guidance serves the corresponding product-document workflow.
- UI work: The iteration loop skips some checks to prioritize quick browser feedback.
- Testing: A test skill uses code coverage and changed files to select the relevant portion of the suite rather than running everything.
- Goal execution: Decisions made by the model are retained so they can be reviewed later.
These skills specialize the work inside the loop without replacing its basic structure.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make recovery possible after context compaction
This approach has a cost: retrieving and understanding the relevant documents consumes context. Cichra reports that initial research can use roughly half the context window. He nevertheless tentatively describes the approach as working over the preceding half year. In his own sessions, he reports twenty or fifty context compactions without losing the ability to continue, because important information survives or can be retrieved again. These are personal experience reports, not measured reliability results.
The intended outcome is a multi-hour session in which an agent can pursue a clear goal autonomously while operating within explicit rules. That requires more than retaining every detail in the current conversation. It requires a way to recover the details that matter when the conversation no longer contains them.
Decision records preserve why architectural choices were made; product documents preserve why features exist; readable executable scenarios connect those intentions to behavior. Design systems extend the same discipline to interfaces, including enforceable constraints such as prohibiting inline styles outside the designated system. The harness connects those materials to the work itself: a change encounters a check, the check points back to intent, and the next revision can use that intent.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
How readable Gherkin scenario steps connect to executable code, with examples in several languages.
Reference for checks triggered during commits and pushes, including rejection behavior and bypass options.
Further reading
Michael Nygard's lightweight approach to recording architectural context, decisions, status and consequences.
- Introducing Spec27Article
Safe Intelligence's April 2026 announcement of specification-driven validation for AI applications and agents.
SQLAlchemy examples explaining implicit database queries, eager loading and guards against unwanted lazy loads.
Read the complete timestamped transcript
- 0:00
[upbeat music] Hi, I'm Michal.
- 0:16
Uh, welcome to Capturing Decisions for Humans and AI Alike.
- 0:22
Yesterday, with a team from Safe Intelligence, we have released Pact.27, a new product to test agents. Before that, I was in Microsoft, Red Hat, and spent ten years working on a single product.
- 0:35
The consistency problems we face with AI and the story of capturing decisions show up in every product I have seen, and these notes are distilled from that experience. And you can find me at the booth.
- 0:48
Um, so BDD, PRD, ADR, like this lot of acronyms, uh, why does any of it matter? So let's unpack it from the end.
- 0:59
You probably know this story. Uh, I hope it's not an urban legend, uh, but scientists put five monkeys in a cage with bananas on a ladder,
- 1:07
then gave them a cold shower every time a monkey tried to get a banana.
- 1:11
Other monkeys beaten up the poor fella. Then they replaced the monkeys one by one, and none of the originals remained, and yet they have beaten up every monkey that tried to climb the ladder, not knowing why.
- 1:26
So humans and LLMs, they suffer from the same trait: limited context. People forget. LLMs, context compacts. Humans leave. LLMs have no memory. After a while of operating a product, the team starts asking, "Why do we have this flow?
- 1:44
Why is this goal of this feature? Why is this code shaped like that? Why-- where does this belong?" And you might not have the founding engineer available to answer.
- 1:56
And these problems show in every org, uh, maybe with AI much sooner than they used to.
- 2:03
So ADR is Architecture Decision Record. It records why you do something and how you enforce it or how you wanna do that. And you can cover examples by reference docs and code snippets.
- 2:18
For example, we split code in layers to prevent N plus one queries. We enforce that split by linting imports in modules. And we also enforce reading from database, returns, um, plain shapes instead of ORM objects, so we cannot, um, cannot make these, uh, these queries and to prevent duplication.
- 2:38
And also linting it by module imports and another like fifty ADRs that define the architecture of the product.
- 2:47
There is not a single format that, that you need to use. It's just a concept. Um, it's a text, so there is no specific, uh, way how to enforce it.
- 2:58
You still need a tool to enforce it. But the tool will tell you that this is the rule, why are you doing this, and how are you supposed to fix it.
- 3:08
Then the agent will go and try to find this document, why this reason exists, and more information about how to fix it. Also, you can define, like, which files it actually concerns to, like, is it some Python files or some folders, and how you actually enforce it.
- 3:26
PRD is a Product Requirements Document, uh, that's something lighter. When you're building a feature, you describe why that thing exists and what problems it solves and how user goes through the app to actually interact with it.
- 3:41
What's the journey through the application. It can be very light. It doesn't need to be really long and exhaustive, like a massive document. Uh, you can just capture why the problem and the goal and the journey that connects them.
- 3:57
And it's not just for the agents, but also for you six weeks from now when you forget why you did that.
- 4:07
Now BDD, um, it's a Behavior-Driven Development. You have probably seen Spec-Driven Development lately, uh, but if you practiced it, uh, you might have suffered the same thing as me.
- 4:21
How do you validate that the product actually adheres to the spec? It's a markdown document. You describe how it's supposed to work, but how do you know it actually works like that?
- 4:31
One thing harder than reading an AI code is reading AI tests. Um, so what if you had an intermediate layer that actually describes how the product behaves in a human language?
- 4:46
And BDD is not new and shiny, but it's, it can be executable and readable,
- 4:52
so enter Cucumber. It's almost forgotten, suddenly useful again. It's definitely easier to review than your average test.
- 5:02
You can connect scenarios directly to your PRDs and critical user journeys. It can be readable, executable, and it closes the loop that a Spec-Driven Development leaves open.
- 5:15
These rules, uh, these specs are later parsed by steps, and they are executed as code. But what you can do is that you can actually write and read these, and you can review these, and you can understand these.
- 5:30
The language is on you. It doesn't need to be, um, enforced. Like, you-- There are multiple ways how to write these, uh, these features. And
- 5:43
that's it. But they describe how you're supposed to go through the application, why this thing exists, and how it runs. And similarly, they can refer back to all the documents that you have about why things exist.
- 6:00
So, and as a bonus, making consistent UIs with agents is just another level of hard. Like design system and pattern library are the way to build consistent UIs. Like that was the way before AI, and it is the way now.
- 6:18
So you document your language. You say, for example, "A primary button is this and that. It is blue, it has this shape, it has this color, and it's this size."
- 6:26
And you say your rules. You say, "We will have only one primary button visible on a site at any, on a, on, on a page at any point in time."
- 6:35
And then you can enforce these rules. Similarly, you define components and patterns. So for example, if you have multiple colors of these buttons and multiple states, you define components and you define previews, and you demonstrate how they work, and you create snippets of previews so you can actually see them, and the agents can see them.
- 6:57
And then you can go and review and like, "Do these actually adhere to the principles that I have? Do they adhere to the visuals?" And then you reuse them.
- 7:04
As with code, you build these from the ground up, from small pieces into bigger ones. You compose them, and you reuse them. Otherwise, it's, uh, chaos, like with the code.
- 7:18
So cool. These are cool ideas, but how to actually enforce this?
- 7:25
So my team and agents stick with it. How do I keep it consistent? Well, with the loop.
- 7:32
So you probably have heard about closing the loop, reinforcement loop, the harness, how to remind the agent of their rules and how to follow them.
- 7:44
So our loop is simple. It is Git hooks, skills, CI, and linters, and bunch of other checks. Agent's goal is to deliver a pull request, and they, to do that, they need to use Git.
- 7:59
So we use Git hooks, Git hooks to run predefined tasks, and these tasks are later executed on a CI. They are the same tasks that they are executed as, as hooks.
- 8:09
If, for example, agents would get lazy and not wanna execute them or skip them, then they get caught.
- 8:14
And we include linting, formatting, type checking, code duplication, architecture checks, document li- linting, everything that's, that's possible.
- 8:23
So there was a time where code reviews were about style and tabs and spaces, and there is no space for that anymore. All these things are not for discussion.
- 8:33
They are rules, and they are enforced, and they are automated because there is no space for discussion about these anymore. It's more about the high level concepts.
- 8:43
What you cannot find, you cannot enforce. So for example, we enforce architecture of the product and of the code. We separate modules, um, and their imports, so what you can use from where.
- 9:00
For example, our end-to-end BDD test suite cannot access database, so we forbid from accessing any module that could access database and basically force the module to, the modules to iterate without database and really use only the browser features of the application.
- 9:16
Similarly, in the product itself, we enforce we cannot talk to database from rendering templates, so we know that there are no N+1 queries ever. We just define ways to prevent these problems from happening ever.
- 9:30
You cannot keep finding them. You need to prevent them entirely.
- 9:36
Then the com-- the agent tries to commit it and push it, and they get feedback on the commit and get rejected, and they get linked back to the document, and they go read it and fix it and iterate.
- 9:50
So there are some drawbacks. Um, it is... Oh, sorry, it's not drawbacks. Um, so this loop is generic, uh, this loop where they do some work, they, they push it, and they get feedback, and they iterate.
- 10:04
But the loop can be multiple things, right? Like sometimes you're working on a product feature, sometimes you're working on a UI, sometimes you're working on more backendish sh- like backendish things.
- 10:14
So that loop is the same, but what changes is the focus of the loop. So we have different skills. Uh, there is ADR that whenever there is an ADR mentioned, the agent will look up ADRs, how to operate with them, uh, how to find code that affect, that's affected by these ADRs.
- 10:32
For PRD the same. For w- for UI loop, we actually skip bunch of checks and rather force it to iterate in a browser quickly.
- 10:42
And test skill that actually identifies tests to run based on code coverage and file changes, so we run just the focus part of the suite and not the entire suite.
- 10:53
And some goal execution to actually keep decisions that the model made so we can review them later. But all of these provide focus in the loop, but the loop stays, stays the same.
- 11:04
There are drawbacks. Uh, it is very context heavy. Like you can run out of half of the context, uh, in, um, starting the research. Um, but I have no fear of context compacts like this actually for like last half year actually works, I think.
- 11:22
So in my sessions, there are twenty, fifty context compacts, and it's, it's okay because the important things survive, and the agent will always look them up again. So and that's the goal anyway, right?
- 11:37
Like you want to have multiple hour sessions with a clear goal that agent can operate autonomously with the rules that you define. So that's the goal anyway, like.
- 11:48
So there are decisions that you can record. There are parts of the product that you can describe why these exist. There is, um, Cucumber or BDD that can have executable specifications that you can actually rev-- read and review and understand.
- 12:08
Design systems can help you to build consistent UI from components and, um, again, enforce it. That, for example, there are no inline styles anywhere else. And you employ harness to loop it all together.
- 12:24
So may the spec be with you. That's it. [applause] [outro jingle]