DocsRequirements: the owner's own words
Requirements: the owner's own words
An issue and a PR body are written by an agent, and an agent can be wrong. The owner's own words are the test of a feature. A review that reads only the diff, the PR body and the rules can pass a change that no word of the owner asks for.
When review.requirements.enforce is on, desk checks each change against four sources.
| Source | Where it comes from |
|---|---|
| The owner's prompts | The transcripts of Claude Code on this machine, for the repository and its worktrees. This includes the messages that the owner types while an agent works. A quote that these do not hold is also looked for in the sessions of every other project of the last 30 days, because the owner types in the folder where a session started. |
| The owner's prompts of other projects | The packet also holds the prompts of other projects that belong to the repository: a prompt in which a quote was found, and each short prompt (2,000 characters or fewer) of the same session that holds 2 or more of the words of the change. The packet marks each one "another project". A prompt of any other session, and a long pasted text, stay out of the packet, because a headless review sends the packet to the engine. |
| The owner's instruction files | AGENTS.md, CLAUDE.md and the files of review.requirements.instructions. What they ask for is asked for by the owner. See Instruction files. |
| The linked issues | The issues in the **Issue:** field of the PR, in "closes #n" words, and in commit messages. The whole body and every comment. |
| The specs | The design docs that the PR and the issues point to (docs/...md). |
| The register | A file of the repository with the standing requests of the owner as dated quotes (review.requirements.register). |
What changes
| Step | What desk does |
|---|---|
desk pr check, desk pr create, the gh hook |
A PR of a type in review.requirements.prTypes needs the section ## Owner's request. Each quote in it must be in an owner prompt. A quote that no prompt holds refuses the PR. |
desk review |
The packet has the section "Requirements" with the quotes of the PR (found or not found), the linked issues with their comments, the specs, the register and the owner's prompts. |
| The owner's review of the PR | The comments "Feedback of the owner" on the PR itself go in the packet. Each point is a requirement: the reviewer writes a row for it, and a point that the diff does not meet is a blocker. |
| The reviewer | It writes one requirements row for each statement of the owner, and one unrequested row for each feature, screen, table, route or setting that no statement asks for. It also searches the chat history with the chat-recall tools. |
desk report |
A row that is not met, an unrequested change and a quote that no prompt holds each become a blocker (REQ-1, REQ-2, REQ-3). They go through the same human gate as other findings. |
| The verdict | "Review incomplete" when the reviewer wrote no requirement rows, when no prompt could be read, or when the findings of a PR name no reviewer or name the author. |
desk questions review |
The review of a decision reads the whole issue, the specs and the owner's prompts first. It reports a question that assumes a design that the owner did not ask for (presupposes), an option that goes against the owner (contradicts_owner), a question that the owner already answered (already_decided) and a missing option that the owner described. |
The reviewer is not the author
The findings of a PR come from a reviewer that did not write the PR: a desk-<profile> agent, a headless engine (--engine), or a person. The agent writes its name in "reviewer" in findings.json. A headless engine is a reviewer by itself. A branch self-review in desk preflight has no second reviewer, so the rule applies to PRs only.
The name is an attestation. The tool cannot prove who wrote the file.
Write the quote
## Owner's request
- "scale the models up with the load and down when it falls" (2026-01-02, session 1a2b3c4d)
- "build it the way an autoscaler packs nodes" (2026-01-02)
- Find the words:
desk requirements --terms <words of the change> [--issue <n>]. Also search the chat history withrecall_user_prompts. - Copy each quote exactly. Put it in double quotes, or on a line that starts with
>.…or...joins two parts of one prompt, and each part has three words or more. - Check the file:
desk pr check --title "<title>" --body-file <file>.
If no prompt asks for the change, the owner did not ask for it. Stop and say so.
Turn it on
In .desk/config.json:
"review": {
"requirements": {
"enforce": true,
"register": ".desk/owner-requests.md",
"terms": ["words that always select a prompt"],
"prTypes": ["feat"]
}
}
For every repository under some folders, set it in ~/.config/desk/policy.json. The policy also applies to a linked worktree of such a repository, wherever the worktree is:
{ "paths": ["~/code/personal"], "requirements": { "enforce": true } }
| Field | Default | Meaning |
|---|---|---|
enforce |
false |
The verdict and the PR check use the owner's words. With false the packet still shows the section. |
register |
none | A file with the standing requests. Its quotes are checked against the prompts. |
terms |
[] |
Words that always select an owner prompt for the packet. |
recent |
30 |
The newest owner prompts that every packet holds. |
maxChars |
40000 |
The most characters of prompts of the repository in a packet. The prompts of other projects take up to a quarter of this number more. |
prTypes |
["feat"] |
The PR types that need the section ## Owner's request. |
projects |
[] |
Folders of other checkouts whose sessions belong to this repository. |
instructions |
["AGENTS.md", "CLAUDE.md"] |
Files with the standing instructions of the owner. See Instruction files. |
Instruction files
AGENTS.md, CLAUDE.md and the files that you add to review.requirements.instructions hold what the owner always wants, for example "Never put a real path or a real name in code". They count as the words of the owner:
- The packet has the section "Owner instructions" with each file. The reviewer writes a
requirementsrow with the sourceinstructionsfor a statement that applies, and does not report a part of the diff asunrequestedwhen such a statement asks for it. - A quote in the section "Owner's request" of a PR body, or in the register, may come from such a file. The check says "found in the owner instructions of
". - A path in the repository is read at the base branch (
origin/mainby default), so a PR cannot add the instruction that it needs. When the base ref does not exist, the working tree is read. - A path that starts with
~or is absolute is read from the disk. A file of the owner outside the repository, such as~/.claude/CLAUDE.md, goes in the policy file~/.config/desk/policy.json:{"requirements": {"instructions": ["~/.claude/CLAUDE.md"]}}. The policy adds to the list of the repository. - The packet goes to the engine of a headless review (
--engine), so it sends these files too, up to 12,000 characters for each. Name only files that may go there.
Limits
- The prompts come from the transcripts of Claude Code on the machine that runs the review. A CI runner has none, so the quote check is skipped there and the packet says so.
- Sessions of other tools (Codex, Hermes) are not read. The chat-recall tools of the reviewer cover them.