{"slug": "documenting-code-nobody-remembers-a-git-history-draft-pipeline", "title": "Documenting Code Nobody Remembers: A Git-History Draft Pipeline", "summary": "A developer created a Python script that builds a documentation context pack from git history, enabling AI models to draft documentation with cited evidence instead of invented rationale. The tool extracts recent commits, blame lines, and markers like TODO and FIXME, and forces claims to reference commit hashes, addressing the gap between AI drafts and human sign-off in code documentation.", "body_md": "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.\"\n\nThe ticket said: \"document the billing module.\" Six files, zero inline comments, three quiet years in git. Inside `proration.py`\n\nthere is a constant, `0.095`\n\n, that no test explains. Blame says six years old; the commit message says \"fix billing.\" You are now a documentation archaeologist.\n\nOne command pinpoints when that constant appeared:\n\n```\ngit log -S '0.095' --oneline -- src/billing/proration.py\n```\n\nThe pickaxe search gives you the commit, but not the reasoning. That split — evidence versus rationale — is the whole job.\n\nA drafting model with no context will politely invent a rationale for `0.095`\n\n. 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.\n\nThe 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+.\n\n``` bash\n#!/usr/bin/env python3\n\"\"\"Build a citations-ready context pack from git history.\n\nUsage:\n    python build_docs_context.py <path> > context_pack.md\n\"\"\"\nimport subprocess\nimport sys\nfrom pathlib import Path\n\ndef git(args, cwd):\n    return subprocess.run(\n        [\"git\", *args], cwd=cwd, capture_output=True, text=True, check=True\n    ).stdout.rstrip()\n\ndef git_quiet(args, cwd):\n    try:\n        return git(args, cwd)\n    except subprocess.CalledProcessError:\n        return \"\"\n\ndef main():\n    if len(sys.argv) != 2:\n        raise SystemExit(\"usage: build_docs_context.py <path>\")\n\n    target = Path(sys.argv[1]).resolve()\n    root = Path(git([\"rev-parse\", \"--show-toplevel\"], target.parent))\n    rel = str(target.relative_to(root))\n\n    print(f\"# Docs context pack: `{rel}`\")\n    print(f\"> Repo head: {git(['log', '-1', '--format=%h %s'], root)}\\n\")\n\n    print(\"## Recent commits touching this path\")\n    print(\"```\n\n\")\n    print(git([\"log\", \"--oneline\", \"-15\", \"--\", rel], root))\n    print(\"\n\n```\\n\")\n\n    print(\"## Blame, first 30 lines\")\n    print(\"```\n\n\")\n    print(git_quiet([\"blame\", \"-L\", \"1,30\", rel], root))\n    print(\"\n\n```\\n\")\n\n    print(\"## Markers that often hide rationale\")\n    for marker in (\"TODO\", \"FIXME\", \"HACK\", \"XXX\"):\n        hits = git_quiet([\"grep\", \"-n\", marker, \"--\", rel], root)\n        print(f\"- `{marker}`: {len(hits.splitlines())} line(s)\")\n\n    print(\"\\n## Open questions\")\n    print(\"- The 'why' is still unanswered. That is the point of this pack.\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\nRun it once, redirect to a file, and the model now has sources instead of guesses:\n\n```\npython build_docs_context.py src/billing/proration.py > context_pack.md\n```\n\nSplit 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.\n\n| Doc section | Model may draft | Human must own | Primary evidence |\n|---|---|---|---|\n| API surface, signatures, parameters | Yes | Review | source code / AST |\n| \"What changed\" changelog narrative | Yes | Review | commit messages, PR bodies |\n| Runnable usage examples | Yes | Yes — execute and verify | tests, CI logs |\n| Rationale (\"why 0.095?\") | Labeled hypotheses only | Always |\n`git log -S` , issues, humans |\n| Security and compliance statements | No | Always | external policy, not the repo |\n\nNote 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.\n\nThe model rules matter more than the system prompt. Three carry the weight: cite a hash, mark gaps as `[UNVERIFIED]`\n\n, and never invent a reason.\n\n```\nDraft reference documentation for `{rel}` using only the context pack below.\nYou cannot run the code and cannot import outside facts.\n\nRules:\n1. Cite a commit hash for every historical claim: \"introduced in 4f3a2b1\".\n2. If the evidence pack is silent, write `[UNVERIFIED]` and stop that section.\n3. Never invent rationale. You may add one labeled hypothesis per open question.\n4. Leave security and compliance headings empty — a human writes those.\n```\n\nA draft is reviewable when the reviewer's job becomes mechanical. If the reviewer is still guessing, the draft failed; send it back.\n\n`[UNVERIFIED]`\n\nis resolved by a human or the section is deleted.`git show --stat <hash>`\n\n.`0.095`\n\nquestion 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.\n\nMonkeyCode'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.\n\nDisclosure: This article was prepared as part of MonkeyCode's product outreach.\n\nToken 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.\n\nDocumentation 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.", "url": "https://wpnews.pro/news/documenting-code-nobody-remembers-a-git-history-draft-pipeline", "canonical_source": "https://dev.to/datago_7777/documenting-code-nobody-remembers-a-git-history-draft-pipeline-58n7", "published_at": "2026-08-29 10:06:17+00:00", "updated_at": "2026-08-29 10:19:12.843336+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "generative-ai"], "entities": ["DEV", "Python", "Git"], "alternates": {"html": "https://wpnews.pro/news/documenting-code-nobody-remembers-a-git-history-draft-pipeline", "markdown": "https://wpnews.pro/news/documenting-code-nobody-remembers-a-git-history-draft-pipeline.md", "text": "https://wpnews.pro/news/documenting-code-nobody-remembers-a-git-history-draft-pipeline.txt", "jsonld": "https://wpnews.pro/news/documenting-code-nobody-remembers-a-git-history-draft-pipeline.jsonld"}}