--- title: "ADR 0017 — Review is for conflicts, and a new doc from an agent is not one" type: decision tags: [signpost, adr, decision] proposed_by: tok_bc09b340db294c709763789154d8113d model: kmem-docs-publisher extracted_at: "2026-10-08T22:40:33.274Z" --- # ADR 0017 — Review is for conflicts, and a new doc from an agent is not one **Status** Accepted; the `conflicts` rule amended for a connection in write mode by [ADR 0022](./0022-agent-writes.md), which also makes every agent change wait in Review while an org's "Agent writes" setting is off; the consequence about `recall` amended by [ADR 0018](./0018-verification-is-an-org-choice.md), and again by [ADR 0027](./0027-verification-is-tracking.md) · **Date** 2026-09-11 · **Supersedes** nothing · **Amends** ADR 0009 §4's policy set, ADR 0016's default · **Relates to** ADR 0009 (the permission ladder), ADR 0016 (an assistant writes directly by default), `docs/TAXONOMY.md` §7 (the two-grid model), `packages/core/src/permissions/clamp.ts` (the clamp), `docs/MCP.md` and `docs/AGENT-INTEGRATION.md` (what an agent is told) ## Context The instance write policy had three values. `open` applied every agent write, `review` queued every agent write, and `locked` refused every one. Production shipped `review`, and the field evaluation on 2026-09-11 measured what that means for a person on their first day. **The queue filled with decisions nobody needed to make.** An agent connected to an empty organization proposes the first docs — a README, a decisions folder, a glossary. Every one of them is a create at an address nothing stands at. A person then opens Review and accepts eleven changes that could not have destroyed anything, because there was nothing at any of those addresses to destroy. That is not review. It is a receipt, collected one click at a time, and the cost is paid on exactly the day a new customer is deciding whether the product works. **The act that is worth a person's attention is the one that can lose work.** An agent that rewrites a doc somebody wrote last month can be wrong in a way no reader will notice: the new version reads as confidently as the old one and the old one is gone from the reader's view. That is the failure the queue was built for, it is what a person is actually able to judge — the diff has two sides — and it is a small fraction of what an agent writes. **A queue that mixes the two trains people to clear it.** ADR 0016 already recorded this: "a control that is exercised without being read is a wall people click through, and counting it as a control is how a system gets credit for safety it does not have." Eleven harmless creates ahead of one destructive rewrite is the arrangement most likely to get the rewrite accepted unread. ## Decision **A new doc from an agent lands in Docs. A change to an existing doc waits in Review for a person.** That sentence is the whole rule. It is the value `conflicts` of `SIGNPOST_WRITE_POLICY`, and it is the production default. Precisely, for an agent principal under `conflicts`: - A write that **creates a doc at an address where no live doc stands** applies. - Any write that **touches a doc that is already there** queues a proposal — an update, an edit, an append, a delete, a write against a stale base, and a create whose title resolves to an address something already occupies. - A doc above `open` visibility queues whatever the policy says, exactly as before. The ladder decides first and this value cannot widen it. - The duplicate check keeps today's outcome: a write whose text is within cosine 0.92 of an existing doc is answered as a duplicate rather than landing as a second copy. - A person's write is unchanged at every policy. The queue was never about them. The other three values keep their meanings, and `review` remains available for an organization that wants every agent write to wait. Two mechanisms carry the rule, because an agent's write is decided by the two-grid model rather than by the ladder: 1. `writeDispositionFor` (`packages/core/src/permissions/clamp.ts`) gains the `conflicts` branch, reading `WriteClampInput.targetExists` — a required field, so no call site can leave the fact out. 2. `assistantColumnForPolicy("conflicts")` is `write`, because a create must apply, and `conflictPolicyCeiling` narrows the resolved capability to `suggest` for a change to an existing doc. `dispositionFor` in `services/commit.ts` applies it through `narrowestAssistantCapability`, which is the one combinator for "two values, and the answer must not be the permissive one". ## The alternative that was rejected **Keep `review` as the default and make the queue faster to clear** — batch accept, a keyboard path, better cards. It was rejected because it optimises the wrong quantity. Every improvement to the speed of clearing a queue also improves the speed of clearing it *without reading it*, and the queue's whole value is that somebody read it. ADR 0016 already found this the hard way on a queue of 38 items, and the batch endpoint that came out of that work is in the product and still correct — for a batch of changes that each deserve a decision. The measured difference is what settles it. Under `review`, a first session's eleven creates produce eleven decisions and zero averted losses. Under `conflicts`, they produce zero decisions, and the next rewrite of a doc a person wrote produces exactly one — which arrives on an empty queue, where a person reads it. Two smaller alternatives, and why not: - **Decide per folder rather than per instance.** There is no grant table yet (`services/permissions.ts` derives both grids from the ladder), so a per-folder policy is storage this wave would have to invent. When that table lands, `conflicts` is a value a space can carry and nothing above it changes. - **Queue a create whose text is close to an existing doc.** That is the duplicate check, it already exists, and it already answers. Folding it into the policy would give one behaviour two owners. ## Consequences - The production default becomes `conflicts` in `wrangler.jsonc`. `apps/worker/vitest.config.ts` stays pinned at `review`, so every suite that is about something else keeps the behaviour it was written against, and the policy is tested where it belongs. - An agent's first session on an empty organization now writes docs that are immediately readable by `browse` and `read` — which is the second half of ADR 0016's own argument about an agent that cannot see its own work. **Amended 2026-09-16.** This bullet also named `recall`, and that was not true: ADR 0016 control 3 held every unreviewed agent claim out of `recall` in every org. ADR 0018 makes that control an org's choice. In an org that does not use verification — every new org — `recall` returns the new docs at once. In an org that does, `recall` returns them once a person accepts or verifies them. **Review for a change to an existing doc stays in both modes**: this ADR's queue prevents the loss of a doc a person wrote, and ADR 0018 does not change it. **Amended 2026-09-17.** [ADR 0027](./0027-verification-is-tracking.md) removes the quarantine in both modes, so `recall` returns the new docs at once in every org. The sentence above about an org that uses verification is historical. With verification on, the new docs rank below verified text. A change that waits in Review is still in no answer. - The copy changes everywhere an agent or a person reads it: the connection document, `SKILLS.md`, the MCP tool descriptions, the `because` sentence on every write response, `docs/MCP.md`, `docs/AGENT-INTEGRATION.md` and `docs/ARCHITECTURE.md`. One sentence, the same in every place. - **A leaked write credential can now create docs without review on the default policy.** It could already, under ADR 0016's reading of `open`; what is new is that this is the shipped default. The compensations are unchanged and are ADR 0016's: the ladder floors anything above `open` at `never`, the link's own scope is one of the four folded values, the session write budget degrades to a queue, and a whole sitting is undone in one act. What `conflicts` adds on top of `open` is that the same credential cannot silently rewrite a doc a person wrote. - `docs/SECURITY.md`'s known-weakness entry for ADR 0016 still applies and is narrowed by this value rather than widened.