Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

A drafting model can produce a useful getting-started README for a Python library if you limit what it is allowed to write. Let a script collect the facts a static scan can verify, such as public function names, parameters, annotations, and docstring presence. Give the model only the skeleton sections that depend on those facts. Keep install steps, interpreter requirements, sample output, license meaning, and support contacts with a maintainer, and block the merge until a checker passes. This approach controls the process. It does not prove the finished README is correct. As the article’s author, Avery Lin, puts it: “The method is process control, not proof that the resulting README is correct.”

Why split the README into two lanes

Most README failures in library documentation are not spelling errors. They are promises: a Python version that was never tested, an install command that omits an extra, a sample output block that nobody ran, or a support address that goes nowhere. A model left to write the whole file will fill those gaps with plausible text. The approach described by Avery Lin in a DEV Community post titled Generate How-To Skeletons From Signatures, Then Gate README Promises With a Lane File assigns each kind of content to a lane. The draft lane holds material a machine can copy from source. The human lane holds claims that a person must be able to defend.

The five-step workflow

1. Freeze a public-symbol inventory

Walk the package’s Python files with the standard library ast module and record each public top-level function: its name, positional argument names and annotations, return annotation, whether it has a docstring, and its source line number. Write the result to a JSON inventory and compute a digest over it. If the package defines an __all__ list, record the exported names too, because that list is the closest thing a package has to a declared public surface.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Write the lane file by hand before drafting

Before any model call, write a lane file that assigns each README section to an owner. The outline and parameter tables go to the draft lane. Interpreter requirements, install commands, extras, observed output, license meaning, and support contact stay in the human lane. Any human-owned value that has not been supplied and signed off should remain visibly marked, for example as TODO(human), until a person provides a claim they can defend. The lane file also records the inventory digest it was built from.

3. Draft only inside the allowed skeleton sections

Give the model a prompt that tells it to rewrite only TODO(model) blocks, to copy parameter names and annotations exactly from the inventory, and to leave every TODO(human) line untouched. Treat the prompt as a template for controlling output, not as evidence that the generated text was run or that the procedure it describes works.

4. Gate the README before merge

Run a checker that compares the inventory digest recorded in the lane file with a freshly computed one, searches the README for phrases you have forbidden, rejects any remaining TODO(model) marker, and can reject human-owned keys that are still unsigned. Run these ordinary checks in continuous integration on every change. The article recommends also requiring signed human-owned keys on a release branch, where a stale claim costs more.

5. Attach evidence to each human claim

Each human-owned statement should point to something checkable. Interpreter and extras claims can be backed by the project’s packaging metadata. Sample output needs either a recorded session or an explicit label saying it was not executed. Support text should name the real issue tracker or mail alias the project reads. If the README and the packaging metadata disagree, resolve the underlying disagreement in the project. Do not ask a model to smooth the difference over in prose.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Who writes what

README content Lane How it is verified
Document outline and section order Model draft Maintainer reads the draft before merge
Parameter tables (names and annotations) Model draft, copied from inventory Inventory digest comparison in the checker
Interpreter requirements Human Project packaging metadata
Install commands and extras Human Project packaging metadata
Sample output Human Recorded session, or an explicit label that it was not executed
License meaning Human Maintainer sign-off
Support contact Human Real issue tracker or mail alias

A minimal inventory sketch

The following sketch shows the shape of the extractor. It is illustrative and is not a production indexer. It skips keyword-only arguments, defaults, re-exports, C extensions, and runtime-generated APIs, so treat it as a starting point rather than a complete tool.

import ast
import hashlib
import json
import pathlib

def inventory(package_dir):
    items = []
    for path in sorted(pathlib.Path(package_dir).rglob("*.py")):
        tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
        for node in tree.body:
            if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and not node.name.startswith("_"):
                items.append({
                    "file": str(path),
                    "name": node.name,
                    "line": node.lineno,
                    "args": [a.arg for a in node.args.args],
                    "annotations": {a.arg: ast.unparse(a.annotation)
                                    for a in node.args.args if a.annotation},
                    "returns": ast.unparse(node.returns) if node.returns else None,
                    "has_docstring": ast.get_docstring(node) is not None,
                })
    blob = json.dumps(items, indent=2, sort_keys=True)
    digest = hashlib.sha256(blob.encode("utf-8")).hexdigest()
    return items, digest

A minimal gate sketch

The checker can be a short script. The forbidden phrases below are examples; each project chooses its own list. The sketch assumes the lane file stores the inventory digest under an inventory_digest key.

import json
import pathlib
import re

FORBIDDEN = re.compile(r"(?i)b(production-ready|fully tested|guaranteed|supports all platforms)b")

def check(readme_path, lane_path, current_digest):
    text = pathlib.Path(readme_path).read_text(encoding="utf-8")
    problems = []
    if "TODO(model)" in text:
        problems.append("unfilled TODO(model) block remains")
    if FORBIDDEN.search(text):
        problems.append("forbidden phrase found")
    recorded = json.loads(pathlib.Path(lane_path).read_text(encoding="utf-8"))["inventory_digest"]
    if recorded != current_digest:
        problems.append("lane digest does not match inventory digest")
    return problems

What the inventory can and cannot establish

An AST inventory records syntax-level facts. It can tell you a function is named connect, takes a timeout parameter annotated as float, and has a docstring. It cannot tell you that the default value is safe, that the annotation matches runtime behavior, that the docstring is accurate, or that a documented procedure works on a reader’s machine.

The Python Software Foundation’s ast documentation for Python 3.14 states that successful parsing does not guarantee that source is executable, and that parsing does not perform compiler scoping checks. Read the inventory as a constrained list of facts, not as a test result. ast.get_docstring returns the docstring for supported node types or None, which is why the inventory can report presence but not quality.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The lane digest is a staleness signal. When the public surface changes, a person must revisit the human-owned environment claims. The digest does not validate those claims.

Phrase scanning is a tripwire. Paraphrases can evade it, and a clean scan does not show that the how-to is true.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Costs, limits, and when to skip the method

The workflow adds merge friction, and the source post names several situations where that cost is not worth paying. Before adopting it, ask four questions:

  • How much of the public surface is statically discoverable? If much of the API is created at runtime, the inventory misses it.
  • How fast does that surface change relative to review? If the digest cannot stay current with the code, the gate blocks good changes or passes stale ones.
  • Do readers depend on commands or environment promises? If they do, the human lane carries real weight and needs an owner.
  • Does the package already require executed, signed validation? In regulated packages with stronger controls, this method adds little.

The author advises against the approach for regulated packages with stronger existing controls, for rapidly churning APIs where the digest cannot stay current, and for private scratch notes with no external reader contract. The method also does not execute examples or judge readability.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

About the source

The method comes from a single DEV Community post by Avery Lin. The post discloses that it was prepared as part of MonkeyCode’s product outreach and suggests MonkeyCode’s free model access and free server option as a place to host a narrow drafting pass. Those are the author’s statements about that service. Confirm current features, availability, and terms with the vendor before relying on them.

The workflow itself needs only Python source, JSON or YAML files, Git, and a CI system.

(Source: Avery Lin, DEV Community. Python reference: Python Software Foundation, ast documentation, Python 3.14.)

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.