riekelt/technical-writer1 file

Documenting Legacy Codebases

Use when documenting an existing codebase whose documentation is missing, stale, or untrusted - an inherited system, a legacy application, a repo where the docs lie - or when regrounding a documentation tree against the code, or when someone asks what a system actually does. Encodes the survey-first inventory, the writer-side evidence hierarchy, depth-per-surface rules, the refactor test, dead-or-alive proofs, the quirks-and-findings split, the coverage ledger, the parallel campaign, and the docs-tree skeleton. Use whenever documentation must be reconstructed from the code rather than written alongside a change.

Specification
Skill ID
riekelt/technical-writer/documenting-legacy-codebases
Publisher
riekelt
Repository
technical-writer
Installs
202
Files
1
Synced
Sep 16, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

riekelt/technical-writer/documenting-legacy-codebasesInstalls these files
  • SKILL.md

What this skill tells the agent

Documenting legacy codebases

REQUIRED BACKGROUND: the technical-writing skill (hard rules, kind classification, truth rules, style).

Overview

A legacy codebase has one reliable witness: the code at HEAD. Everything else that speaks about it (names, comments, old documents, diagrams, the memory of whoever is left) is testimony. Core principle: describe how the system works and what to look out for, verified against the code; the code stays the authority on how it is implemented. The deliverable is a docs tree the next engineer trusts and the next refactor leaves untouched: only changed behavior or a new feature sends anyone back to edit it.

When to invoke, and not

Invoke when documenting a system that exists and is under-documented: an inherited or acquired codebase, a system whose authors left, a docs tree that no longer matches the code. A "what does this actually do" investigation that must end in documents also qualifies. Do NOT invoke for documenting a change you are making; the core skill and the document-type skills cover documentation-with-change. Not for arguing a rewrite, which is writing-design-docs, fed by these documents. And not for fixing what the grounding finds: the code fix sits outside this plugin; noting the oddity does not (see quirks and defects).

Survey before prose

Do not start writing at the first interesting file. First enumerate the system's surfaces:

  • Entry points and processes: executables, services, scheduled jobs, queue consumers, request handlers.
  • Commands and endpoints: everything an operator or client can invoke.
  • Configuration: every key, flag, and environment variable the code reads.
  • Data: schemas, tables, migrations, files on disk, external stores.
  • Integrations: every external system touched, with direction and protocol.
  • Build and deploy: how the artifact is produced and where it lands.

Each count is a claim, so the count rule in references/truth.md in the core skill applies: print the command behind it, run it at HEAD, date it. Commands, counts, and dates land in the coverage ledger, where drift is expected; the documents stay still. Derive the docs tree from the inventory, not from reading order.

Depth follows the surface

The tree describes the generic system; the code states its own implementation, and prose never re-documents it. Kind decides the depth:

  • Contract surfaces are exhaustive. What outside parties bind to and cannot read the code for: HTTP endpoints, message payloads, commands, file formats, config keys. These are reference kind, so the core Reference rule applies: every endpoint, every field, every key. documenting-contracts carries the template for endpoints, messages, commands, and payloads; config keys follow the core Reference rule in config-reference.md.
  • Internals get the gist. A descriptive document states the mechanism and its consequences ("the store is append-only; reads take the tip of the chain; an update replaces the whole record"). The classes, database keys, mappings, and call chains that implement the mechanism stay in the code.
  • The refactor test. A finished document sits still while the code is refactored, and changes only when behavior changes or a feature lands. A sentence that a rename would falsify (a method name, a line number, a list of classes) is implementation detail in prose form; lift it to the behavior it implements or cut it.
  • Prose carries no code references. A document names the module or path it describes once, in its opening: the drift anchor the core skill's references/truth.md requires. Running prose stays free of paths, class names, and line numbers; exact file:line belongs in the findings note, where it is working material for the owner.
  • The boundary check: a paragraph that only helps a reader who already has the file open is transcription; delete it or reduce it to its anchor. A detail that survives the check is usually a quirk, and quirks are content (below).

The evidence hierarchy

What a claim may rest on before it is written, in descending order of trust. The hierarchy binds the writer's verification; the page shows one opening anchor per document, and the depth rules above decide the rest:

  1. Code read at HEAD. The source of truth for every descriptive claim.
  2. Tests that cover the path. A test names expected behavior and proves the code executes; reachability in production comes from the wiring proof under "Dead or alive".
  3. Runtime evidence, where it exists and reading it is safe: logs, database contents, live configuration. Date it; runtime evidence is perishable.
  4. Commit history. Evidence for the historical document and for when behavior changed; never a substitute for reading the current code.
  5. Names, comments, existing docs, and human memory. Testimony: quote it, verify it, and only then repeat it. When a name contradicts the behavior, document the behavior and call out the contradiction; the reader who greps the name must land on the warning.

A briefing from the previous owner, an architecture diagram, a "the sync service handles that" all get verified in code before they enter a document; only what the code confirmed gets written.

Dead or alive

Code that looks load-bearing can be unreachable, and code that looks dead can be the production path. Never assume; prove:

  • Alive is shown by wiring: the reference search, the registration (dependency container, router, scheduler, exported symbol), and where checkable the runtime trace.
  • Dead is shown by absence, and the absence evidence is named: "no command, no controller, no reference outside its own tests". A dead-code claim without the search behind it is a guess.
  • Dormant is its own state: wired but disabled, or reachable only from a dead path. Describe it in the past tense or with an explicit wired-but-disabled qualifier; the tense rule in the core skill's references/truth.md forbids present-tense prose about code that cannot currently run.
  • Config keys are checked for binding. A key the code never reads is a dead knob. The config reference marks it dead.

The proof convinces the writer and its command goes in the coverage ledger; the document states the outcome. Dead code earns prose only where a reader would trip over it, and that mention is a quirk.

Kind discipline while grounding

The core skill's classification table governs every document you touch or create. Reference kind is settled by the depth rules above, and a runbook you touch follows writing-runbooks; the remaining kinds:

  • Descriptive documents match the code's behavior exactly, in current tense, each naming the code it describes in its opening so drift checks have an anchor (the core skill's references/truth.md).
  • Normative documents found violated are never watered down. When the code breaks a stated contract, the contract stands, and the violation goes in the findings note. Writing "the system does X" where X is a bug, without flagging it, canonizes the bug as specification.
  • History is excavated and labeled. What git log shows goes in the historical document as history. Inferred intent ("this appears to have been a workaround for...") is labeled as inference and carries what it is inferred from.
  • Obsolete documents get a banner, never silent deletion, per the core classification rule; the owner decides removal.

Quirks and defects

  • Quirks are content. Surprising but real behavior is the "what to look out for" the tree exists to carry: an update that replaces the whole record, a table that breaks the pattern. A quirk goes in the owning document, stated plainly as behavior, however odd it looks.