# 0024 · A change to a page can be suggested, and accepted in one step by anyone who can edit it

**Status:** Accepted · 2026-10-27. It amends [0021](https://codna.me/docs/adr/0021-agents-are-members.md): an agent still
edits nothing it was given, but may suggest changes to it.

## Context

Since 2026-10-27 an automation can start a Claude routine ([0023](https://codna.me/docs/adr/0023-automations-reach-outside.md)),
and agents do work nobody asked for in the moment. The first routine, `decision-check`, checks each
new page in `wiki:decisions` and writes down what should change. On its first run it found two real
gaps. A person then read its notes and typed each change into the page again by hand.

That copying is where a proactive agent loses what it saves. The point of an agent working on its
own is that a person only has to approve what it did, in one step. CoDNA has that step for links
already ([linking.md](https://codna.me/docs/linking.md#suggested-links)): an agent proposes, someone who can edit the
page accepts or rejects, and an accepted link is an ordinary edit. For a change to the text there is
nothing like it. An agent that can edit has two choices, and both are wrong for a page people wrote:

- **Edit it directly.** The change is in the history and can be reverted, but nobody looks at it
  before readers see it, and an editor learns of it only by chance.
- **Write the change somewhere else,** as `decision-check` does, and hope someone copies it.

An [agent member](https://codna.me/docs/adr/0021-agents-are-members.md) has neither. It may not edit what it was given, so it
cannot even propose a fix to a page it found wrong.

The 2026-10-25 decision that CoDNA sits under the AI tools stopped work on the editor but kept
"checking, not writing": CoDNA's own pages should turn toward reviewing what agents drafted. This is
the smallest piece of that.

Most of what it needs is already built:

- **Edits that name their text.** `edit_document` does not take a new body. Each edit names the
  exact text it replaces or goes beside (`internal/markdown/edits.go`), so the same edits apply to a
  page that changed since they were written, and are refused, not guessed at, when their text has
  gone.
- **Every save is a revision** with an author and a summary, and `revert_document` undoes any of
  them.

## Decision

**A suggested change is a set of edits, kept until someone who can edit the page accepts or rejects
it.** Accepting applies the edits to the page as it is then, as one ordinary revision.

### What a suggestion holds

- **The edits,** in `edit_document`'s shape (`replace`, `insert_after`, `insert_before`, `append`,
  `replace_section`, `delete_section`), and a new title or tags if wanted. Never a whole new body:
  one written against yesterday's page would undo today's changes when accepted.
- **Why,** in a sentence or two. It is required: a change with no reason is one the editor has to
  work out backwards.
- **Who suggested it, and the version it was written against.**
- **The diff it made against that version,** kept when it is made, so the reviewer sees exactly
  what the suggester saw.

Making a suggestion tries its edits first, as a dry run does. One that does not apply to the page
as it is now is refused at once, with the reason, rather than queued to fail later.

### Who may suggest, and who decides

- **Anyone who can read a page may suggest a change to it,** except in `raw`, which is never edited.
  That is the rule links follow: noticing needs read, deciding needs write.
- **Someone who could edit may suggest instead.** A routine runs as the person who made it, who can
  usually edit. Suggesting is how it leaves the decision to a person, so editors are offered it too.
- **Anyone who can edit the page decides.** The suggestion waits in their inbox and on the page, as
  a suggested link does, and one decision settles it for all of them.
- **An agent member may suggest** on pages shared with it, and still edits none of them. Its
  suggestions go to the page's editors, not to the people responsible for the agent: whoever can
  change the page is who should judge a change to it.
- **A suggestion is seen by its suggester and the page's editors.** Other readers do not see it: it
  is not part of the page until it is accepted.

### Accepting and rejecting

- **Accept** applies the edits to the page as it is now, through the code `edit_document` uses, as
  one revision. Its author is the person who accepted. Its summary names the suggester and the
  reason, such as "Suggested by Dana (decision-check): add the What changed section".
  `revert_document` undoes it like any other change.
- **When the page has moved on** and an edit's text is no longer there, the suggestion says it no
  longer applies, and which edit, and offers only Reject. CoDNA does not guess where the text went.
- **Reject** takes an optional reason, which the suggester can read. A rejection is durable: the same
  edits suggested again for the same page are refused, saying they were rejected, as a rejected link
  is never proposed again.
- **The suggester may withdraw** a suggestion that is still waiting.
- **The suggester is told** when someone decides: an inbox notification, and over MCP the status and
  the reason. That is how a routine's next run learns what was taken.

### Where it shows

- **MCP:** `suggest_edit` takes what `edit_document` takes, plus the reason, and answers with the
  suggestion, its diff and its url. `pending_decisions` lists suggested changes beside suggested
  links. `decide_edit_suggestion` accepts or rejects one, and `list_suggestions` lists a page's, or
  the caller's own with their status. An agent's tool list gains `suggest_edit` and
  `list_suggestions`.
- **Web:** the inbox gets a "Suggested changes" group. Each item shows the page, who suggested it and
  why, and the change as a diff, with Accept and Reject. A page with suggestions waiting says so at
  the top for its editors, and opens the same list. The editor itself does not change: there is no
  suggesting mode.
- **Live, and told:** a trigger beside the table wakes the inboxes of the page's editors, and of
  the suggester once it is decided, as suggested links do; the suggester's notification is written
  with the decision. No outbox event yet: nothing would consume one until automations trigger on
  suggestions.

### Limits

- At most 20 suggestions waiting from one suggester on one page, and 200 from one suggester in all.
  An agent can suggest faster than anyone reads, and an inbox that fills up gets ignored.
- The same size limits as an edit.

### Storage

A new table, `edit_suggestions`: the document, the base version, the edits as JSON, a new title and
tags if any, the reason, who suggested it, its status (pending, accepted, rejected or withdrawn), who
decided, when, and why, the version that accepting made, and the diff. A hash of the edits is unique
per document, which is what makes a rejection durable. The migration only adds. A page's suggestions
go when the page is deleted for good. Like suggested links, they are not in an export: until
accepted they are not part of the page.

## Consequences

- An agent's proposal lands in one step, and the page's history says who suggested the change and
  why.
- Editors get a new kind of inbox item. The limits and durable rejections keep it from turning into
  noise.
- **An agent given read can now put text in front of a page's editors.** It appears as a suggestion,
  with its suggester named, and changes nothing until a person accepts it. Sharing with an agent
  already meant trusting what it says; now its editors also judge what it proposes.
- The skill that tells a routine how to work with CoDNA changes: what waits on a person becomes
  suggestions, and a run's page links to them.
- A suggestion's diff is computed against the version it was written for. If the page changed, the
  reviewer sees that diff and a note that it will be applied to the newer version.

## Alternatives rejected

**Let agents edit, and revert what is wrong.** It needs no new mechanism. But nobody reviews the
change before readers rely on it, an agent member could not use it, and people stop trusting a page
anyone's agent rewrites.

**A draft copy of the page in `output`, merged by hand.** That is what `decision-check` does now,
in effect. A whole new body fights every edit made since, and merging it is the copying this is
meant to end.

**Comments with suggested text,** as Google Docs and Claude Docs have. CoDNA has no comments, and
building them is editor work the 2026-10-25 decision stopped. A suggestion is the part of comments an
agent needs.

**Branches or pull requests for pages.** That is git's model, and it suits code. For a page, a
branch is a whole copy with its own history, and most suggestions are a sentence.

**A three-way merge of whole bodies on accept.** Edits that name their text already re-apply to a
newer page, and say plainly when they cannot. A merge would succeed more often and be wrong in ways
nobody notices.

## Settled when it was accepted

Five questions were open while this was proposed. On 2026-10-27 each was settled as proposed:

1. **Agent members may suggest,** which amends 0021.
2. **People who can only read may suggest,** as they may propose links.
3. **A suggestion is accepted as it is.** Editing it first would open the editor with the change
   applied, which is editor work; it can come later.
4. **The limits are 20 waiting per suggester per page, and 200 in all.**
5. **Automations neither suggest nor trigger on suggestions yet:** `actions.suggestEdit` and triggers
   on `suggestion.created` and `suggestion.decided` wait until someone asks.

## Building it

Each step can ship alone:

1. **Core:** the table, the service, the MCP tools, the events, and the agent tool list.
2. **Web:** the inbox group and the note on the page, with the diff.
3. **The skill and `decision-check`:** suggest the changes instead of writing them into the run's
   page.
