Skip to main content
The fair objection to an AI-maintained requirements document: the same system writes the document and the tests, so what stops an entry from saying one thing while its test checks another? The PRD is built so that can’t happen quietly. What an entry says is bound to what its test does: access descriptions are generated from the verified contract rather than written, calculation claims sit beside the real calls that produced their values, and feature assertions appear in the timeline against the recording they ran in. A claim cannot show as verified unless the code actually implements it, and you never need to read test code to know that the sentence you’re reading is the thing that was tested. This page describes the mechanisms, entry type by entry type, and ends with a summary of the guarantees.

Feature tests

A feature test drives the real app in a real browser. The harness records the evidence during the run; the test itself can only drive the app:
  • The video is a screen recording of the app under test.
  • The data snapshots are read from the app’s database, before and after the flow.
  • The service calls are captured at the service boundary as the app makes them.
  • Each acceptance check runs as a real assertion against the page. A failed assertion fails the entry, and with it the build.
One thing can’t be fully machine-checked: whether an assertion is meaningful (a label claiming “shows the total” over a check that would pass anyway). That is kept reviewable instead. Every acceptance check appears in the timeline next to its plain-language label, synced to the recording, so a claim that doesn’t match what’s on screen is visible to whoever watches. The harness also fails a run outright on an uncaught page error or a blank render.

Access rules are derived from the code

Access entries are derived from the code and cross-checked at build time:
  • Access in an app is expressed through two structured mechanisms: procedure guards (public, authentication required, or required scopes) and each procedure’s declared access pattern (rows scoped to the caller, to their org, shared across the app, and so on).
  • Each endpoint’s declared contract is cross-checked against those guards at build time. A contract claiming authentication or scopes the procedure doesn’t enforce fails the build, and vice versa.
  • From the contract, the build derives the scenarios the entry’s test must cover (the anonymous caller denied, the wrong scope denied, the owner’s call works and another user’s doesn’t, each business rule rejects) and fails until every one exists. The scenarios run as real requests against the running backend.
An access entry therefore can’t be made up: the declaration has to match the code’s guards, and the rules have to hold under real requests. Scenario verification is also read-only: the only way a scenario can change state is through a real endpoint call, so a test can’t write the expected result into the database and then assert it.

Concerns are computed from access patterns

Because access is enforced through those structured mechanisms rather than ad-hoc checks scattered through handlers, every endpoint’s effective access pattern is machine-readable. The build reads the verified contract and computes review flags from it: any endpoint that lets a signed-in user read or modify rows beyond their own gets a warning that the permissive access should be verified. The plain-language “who can do this” descriptions are generated the same way. Neither the flags nor the descriptions can be omitted or reworded, by the agent or by anyone else. See Access verification.

Calculation tests must use the real implementation

Build-time gates check every calculation test at two levels: it must import real app code, and every assertion must be computed from an imported call’s result. A restated formula, an assertion on local arithmetic, a same-value conditional, or a dynamic load of app code all fail the build. At runtime, the calls a test makes into the app’s implementation are recorded (function, arguments, returned value) and shown in the PRD view, grouped by the check that made them, and a test whose checks never call the implementation fails. See Verifying calculations.

Tests never call live services

Every service call an app makes (an LLM request, a Slack message, a warehouse query) crosses one statically typed boundary, and PRD tests stub that boundary completely. This makes mutations safely testable: the flow that sends the email really runs, and the PRD records exactly what would have been sent, but nothing leaves the machine. See Services and workflows.

The PRD stays in sync

  • Every endpoint is in the matrix. A build-time validation fails if any API endpoint is missing from the access-control section, so an endpoint can’t be left out of verification.
  • Every entry has a test. The build fails on an entry with no test file, and the test’s title must equal the entry id.
  • Failing tests fail the build. The suite runs in every build. The agent making a change gets the failure immediately and fixes it as part of the change, which is why entries are usually green by the time you review them.
  • Results go stale with the code. When a build changes the app, affected results show as stale in the PRD view until the tests re-run, so a green entry always refers to the code you’re looking at.

Why the framework can guarantee this

These mechanisms work because the app framework leaves exactly one way to build each thing. Every endpoint is a procedure with a declared guard and access pattern; every external call goes through one statically typed service boundary. Build validations reject code that tries to do any of these another way. That uniformity is what the PRD system verifies against. Because access can only be enforced one way, a declared contract can be mechanically checked against the code, and every endpoint’s effective access is machine-readable. Because services can only be called one way, the entire suite stubs and captures them at a single point, which is what makes mutations safely testable. A test harness can’t offer these guarantees for arbitrary code; it can here because the framework constrains what the code can be.

Summary of guarantees

Every guarantee below serves the same property: the plain language you read corresponds, one to one, to test logic that actually ran.

What remains for human review

How much human validation a green entry still needs differs by entry type. API and data-access entries need little. The checks they must cover are derived from the contract, and the contract is cross-checked against the code, so whether the tests check the right things is not in question; the build determines what they check. The review that remains is intent: confirm each needs-attention flag (is the permissive access deliberate?) and confirm the business rules are the rules you want. Feature and calculation entries need your review. The harness guarantees the evidence is real and the assertions passed, but which assertions to write is chosen by the agent. A passing feature test proves the app does what the test says; whether the test says the right thing is yours to confirm. The system’s job is to make that review quick and its material reliable: the video shows the real app, and a criterion only shows green when it’s enforced. Reviewing results walks through how.