# Documenting Code Nobody Remembers: A Git-History Draft Pipeline

> Source: <https://dev.to/datago_7777/documenting-code-nobody-remembers-a-git-history-draft-pipeline-58n7>
> Published: 2026-08-29 10:06:17+00:00

A recurring theme in this week's DEV discussions: AI turned every developer into a reviewer, but nobody wrote the contract between the model's draft and the human's sign-off. That gap hurts most in documentation, where the code itself rarely explains the "why."

The ticket said: "document the billing module." Six files, zero inline comments, three quiet years in git. Inside `proration.py`

there is a constant, `0.095`

, that no test explains. Blame says six years old; the commit message says "fix billing." You are now a documentation archaeologist.

One command pinpoints when that constant appeared:

```
git log -S '0.095' --oneline -- src/billing/proration.py
```

The pickaxe search gives you the commit, but not the reasoning. That split — evidence versus rationale — is the whole job.

A drafting model with no context will politely invent a rationale for `0.095`

. The fix is not a "better" prompt; it is a narrower job description. Feed the model an evidence pack drawn from git history, and force every claim to cite a commit hash.

The script below builds that pack for any path in a repository: recent commits, blame lines, and markers that usually hide a decision. It uses plain subprocess and runs on Python 3.9+.

``` bash
#!/usr/bin/env python3
"""Build a citations-ready context pack from git history.

Usage:
    python build_docs_context.py <path> > context_pack.md
"""
import subprocess
import sys
from pathlib import Path

def git(args, cwd):
    return subprocess.run(
        ["git", *args], cwd=cwd, capture_output=True, text=True, check=True
    ).stdout.rstrip()

def git_quiet(args, cwd):
    try:
        return git(args, cwd)
    except subprocess.CalledProcessError:
        return ""

def main():
    if len(sys.argv) != 2:
        raise SystemExit("usage: build_docs_context.py <path>")

    target = Path(sys.argv[1]).resolve()
    root = Path(git(["rev-parse", "--show-toplevel"], target.parent))
    rel = str(target.relative_to(root))

    print(f"# Docs context pack: `{rel}`")
    print(f"> Repo head: {git(['log', '-1', '--format=%h %s'], root)}\n")

    print("## Recent commits touching this path")
    print("```

")
    print(git(["log", "--oneline", "-15", "--", rel], root))
    print("

```\n")

    print("## Blame, first 30 lines")
    print("```

")
    print(git_quiet(["blame", "-L", "1,30", rel], root))
    print("

```\n")

    print("## Markers that often hide rationale")
    for marker in ("TODO", "FIXME", "HACK", "XXX"):
        hits = git_quiet(["grep", "-n", marker, "--", rel], root)
        print(f"- `{marker}`: {len(hits.splitlines())} line(s)")

    print("\n## Open questions")
    print("- The 'why' is still unanswered. That is the point of this pack.")

if __name__ == "__main__":
    main()
```

Run it once, redirect to a file, and the model now has sources instead of guesses:

```
python build_docs_context.py src/billing/proration.py > context_pack.md
```

Split every doc section into two buckets: what the model may draft, and what a human must own. The line is not about difficulty; it is about whether a wrong sentence causes silent damage.

| Doc section | Model may draft | Human must own | Primary evidence |
|---|---|---|---|
| API surface, signatures, parameters | Yes | Review | source code / AST |
| "What changed" changelog narrative | Yes | Review | commit messages, PR bodies |
| Runnable usage examples | Yes | Yes — execute and verify | tests, CI logs |
| Rationale ("why 0.095?") | Labeled hypotheses only | Always |
`git log -S` , issues, humans |
| Security and compliance statements | No | Always | external policy, not the repo |

Note that rationale falls on the human side. The model can propose a hypothesis, but the commit message "fix billing" is evidence of a change, not proof of intent.

The model rules matter more than the system prompt. Three carry the weight: cite a hash, mark gaps as `[UNVERIFIED]`

, and never invent a reason.

```
Draft reference documentation for `{rel}` using only the context pack below.
You cannot run the code and cannot import outside facts.

Rules:
1. Cite a commit hash for every historical claim: "introduced in 4f3a2b1".
2. If the evidence pack is silent, write `[UNVERIFIED]` and stop that section.
3. Never invent rationale. You may add one labeled hypothesis per open question.
4. Leave security and compliance headings empty — a human writes those.
```

A draft is reviewable when the reviewer's job becomes mechanical. If the reviewer is still guessing, the draft failed; send it back.

`[UNVERIFIED]`

is resolved by a human or the section is deleted.`git show --stat <hash>`

.`0.095`

question goes to a person or a linked issue, not to a plausible paragraph.The steady-state loop is cheap: re-run the archaeology pass when code changes, regenerate draft sections, keep the same open questions in front of a human. Token cost stays low because the pack is bounded by file size, not by the whole repo.

MonkeyCode's free model access and free server option cover both ends of that loop — part of the project's open-source stack. The draft job runs against the free model access, and a cron on the free server option keeps the pack fresh. The free allowance is advertised as 10M tokens at the time of writing; free tiers change, so verify the current terms before planning around them.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Token math stays small. A 400-line module yields a context pack of a few thousand words; mixing prose and code at roughly 0.4–0.75 words per token, one pass lands in the 10k–30k token range. That is noise against a 10M-token allowance. The bottleneck is the human review queue, not the token budget.

Documentation debt is a memory problem. Git history is the memory; a free-tier drafting loop turns it into a first draft; the human owns the final word. If your repository has a module nobody remembers, run the script before you write a sentence — the draft arrives with receipts attached, and for a zero-dollar stack, MonkeyCode's free model access and free server option are a reasonable place to start.
