Model Draft, Human Sign: A Two-Party Documentation Workflow
A documentation page contains many different kinds of promises, and only some of them can be drafted by a model. The workflow that survives review is a two-party handoff: the model produces disposable prose for mechanical sections, while a named human signs every section that encodes a decision. This post defines the boundary with a delegation matrix, then provides a diff script that makes the handoff visible inside the repository.
Why the whole file fails as a delegation unit
Most teams think about AI-generated docs in file-sized units, which forces a false choice between trusting everything and trusting nothing. A model can write fluent parameter tables and step sequences, but it has no authority to state a compatibility guarantee, a security margin, or a deprecation date. The useful boundary therefore sits inside the file, at the level of a section and the type of claim that section makes.
The delegation matrix
The matrix below is the boundary I apply when a documentation task enters the pipeline. Model-draft sections are written to be rewritten, while human-owned sections are written to be signed.
| Section | Delegation | Why the boundary holds |
|---|---|---|
| Usage examples | Model drafts the scaffold | Humans verify semantics against real runtime behavior |
| Parameter and return descriptions | Model drafts | Mechanical restatement of public signatures |
| Install and setup steps | Model drafts | Verifiable by reproduction rather than by authority |
| Error message explanations | Model drafts | Derived from logs and traces the human supplies |
| Compatibility guarantees | Human owns | A promise with support and migration weight |
| Deprecation timeline | Human owns | A schedule set by planning, not by prose generation |
| Security considerations | Human owns | Risk assessment belongs to the accountable engineer |
| Known limitations | Human owns | Honest scope boundaries require judgment about readers |
| Rationale and trade-offs | Human owns | Explains why one design won over its alternatives |
Keep this table inside the repository next to your docs, because the review process needs the boundary visible at merge time. When a model writes into a human-owned section, treat the result as a draft by definition, no matter how confident the text sounds.
The four-stage handoff
The workflow has four stages, and each stage produces an artifact that the next stage consumes.
Write an outline that marks ownership. Create a Markdown file with the final headings and a marker under each one:
draft: modelorowner: human. Human-owned sections start with a placeholder body that saysState: needs owner, so the model knows what to leave alone.Let the model fill the model-draft sections only. This stage is where free inference fits naturally, because the generated text is disposable by design. MonkeyCode's free model access and free server option are sufficient for a drafting loop whose output never ships verbatim. Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Have a named human sign each owned section. A signature line at the bottom of the section, such as
Reviewed by: name | date, turns ownership into a searchable fact instead of a team memory. No signature, no merge, regardless of how polished the placeholder looks.Measure the divergence between draft and commit. A small script compares the stored draft with the final file and reports, for every section, whether the text changed and whether an owned section was left untouched.
The divergence report
The script below implements stage four, and it is deliberately naive so the results stay explainable. It splits both files by headings, then classifies each section as changed, untouched, missing, or an untouched owned section that should have been edited.
import re
import sys
from pathlib import Path
HEADING = re.compile(r"(?m)^(#{1,3} .+)$")
def split_sections(text):
matches = list(HEADING.finditer(text))
sections = {}
for i, match in enumerate(matches):
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
sections[match.group(1)] = text[match.start():end]
return sections
def main():
draft = split_sections(Path(sys.argv[1]).read_text())
final = split_sections(Path(sys.argv[2]).read_text())
for heading, draft_body in draft.items():
final_body = final.get(heading)
if final_body is None:
print(f"{'missing':<38} {heading}")
elif final_body != draft_body:
print(f"{'changed':<38} {heading}")
else:
print(f"{'untouched':<38} {heading}")
if "owner: human" in draft_body:
print(f"{'WARNING: owned section not edited':<38} {heading}")
if __name__ == "__main__":
main()
Run it from the repository root with the draft and the reviewed file as the two arguments.
python docs_divergence.py drafts/quickstart.md docs/quickstart.md
A realistic report looks like the example below, and the warning line is the one that matters most.
changed ## Usage examples
changed ## Parameter descriptions
untouched ## Install and setup steps
WARNING: owned section not edited ## Security considerations
A changed model-draft section means the review loop did its work, while an untouched one is acceptable only when the text was verified by execution. A warning on an owned section means ownership was declared but never exercised, which is a review failure rather than a style preference.
Where the approach breaks
The diff heuristic compares text, not rendered truth, so any claim that describes behavior still needs an execution check. Whitespace-only edits count as changes, which means a cosmetic formatting pass can hide a skipped review. A human can also replace a placeholder with near-identical text and defeat the warning, and duplicate headings collapse in the section map, so each heading must be unique. Teams without a named reviewer should not adopt the sign-off line at all, because an empty signature ceremony is worse than no ceremony. Diagram-heavy documentation is also a poor fit, since the meaning lives in visuals that no text diff can capture.
Who should use the split
The split pays off for teams that generate many pages from the same template and need to know which parts carry real authority. It pays off for solo developers who want a cheap draft loop before they invest their own writing time. It does not pay off for conceptual writing with no factual claims, because there is nothing left to own once the prose is drafted.
The script is a single file, and the next page you generate can be the first one that records who actually wrote its promises.
Top comments (0)