DEV Community

Avery Lin
Avery Lin

Posted on

Model Draft, Human Sign: A Two-Party Documentation Workflow

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.

  1. Write an outline that marks ownership. Create a Markdown file with the final headings and a marker under each one: draft: model or owner: human. Human-owned sections start with a placeholder body that says State: needs owner, so the model knows what to leave alone.

  2. 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.

  3. 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.

  4. 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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)