con un clic
documentation-updater
Updates API docs, README, code comments, and changelog entries.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Updates API docs, README, code comments, and changelog entries.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Reference copy of the operating contract for the defense lens at a human gate — input binding, the six sources of the case for crossing, the untrusted-input and exhibit-marker rules, the evidence whitelist, the degraded-input table, the severity/confidence/variance scales, the output contract, and the escalation table. NOT preloaded into any agent. agents/iron-loop/advocate-critic.md carries this contract in its own body; this file is loadable on demand through the Skill tool by any agent that needs to read the same rules.
Reviews AI-generated code for common pitfalls — over-engineering, missing edge cases, fabricated patterns, hallucinated imports, stale framework idioms, vacuous tests.
Detects AI-generated code that references non-existent packages, APIs, methods, or fabricated patterns.
Paranoid LLM red-team analyst — scans applications that call LLMs for OWASP LLM Top 10 v2 (2025) findings and maps them to MITRE ATLAS v5.4.0 adversary tactics.
Builds the import graph and detects circular dependencies, layer violations, instability mismatches, and cross-module coupling.
Detects which architecture pattern a codebase follows (Layered, Hexagonal, Clean, Onion, CQRS, DDD, Vertical Slice, Modular Monolith, Microservices) with confidence scoring across 7 languages.
| name | documentation-updater |
| description | Updates API docs, README, code comments, and changelog entries. |
| type | skill |
| when_to_load | ["update docs","update documentation","write README","API documentation","add docstrings","doc coverage"] |
| related_skills | ["documentation/changelog-generator"] |
| effort_level | medium |
| tools | Read, Write, Edit |
| model | sonnet |
| tier | 2 |
| dispatch_protocol | v1 |
| confidence_calibration | enabled |
| parallel_safe | true |
| effort_budget | {"max_subagents":0} |
Converted from agents/documentation/documentation-updater.md as part of CTOC v7 B2 leaf-node sweep. Auto-loaded when the user prompt matches a when_to_load trigger.
You update documentation to reflect code changes. Runs in Step 15 (DOCUMENT) of the Iron Loop. You assume documentation drifts faster than code: every rename, every signature change, every new endpoint, every breaking change is a documentation defect until proven otherwise.
docs/ go through the same review as code.doctest, Rust cargo test --doc, TS tsx/vitest, Java JCoTester/Spring REST Docs snippet inclusion).docs/adr/ using the MADR template (adr/madr on GitHub — full or minimal variant, annotated or bare). ADRs are append-only: superseded records link to the replacement; accepted records are never edited in place.docs/ too. Stale ownership = stale docs.llms.txt at site root summarising the docs for LLM ingestion.last-updated > 6 months for a page covering actively changed code is a stale-doc finding.Each category maps to a finding kind in the letter schema below.
| Kind | Trigger | Example |
|---|---|---|
stale_doc | Page's last-updated > 6 months and the underlying code changed within that window | docs/api/users.md last edited 2025-09, src/api/users.py edited 2026-03 |
broken_link | Internal or external link returns 4xx/5xx, or anchor target missing | [install](./install.md) — file moved |
untested_snippet | Fenced code block in docs not covered by a snippet runner | ```python block in tutorial never executed in CI |
missing_adr | Architecturally significant change merged without a matching ADR | New auth provider added; no docs/adr/NNNN-*.md accompanies the PR |
missing_api_doc | New public endpoint / exported function / public class lacks generator-readable docstring | POST /v2/orders exists in router but missing from OpenAPI / Swagger output |
missing_migration_guide | Breaking change in code with no migration entry — cross-links to [[backwards-compatibility-checker]] | Renamed getUser → fetchUser; no upgrade note in CHANGELOG.md or docs/migrations/ |
inconsistent_code_doc | Symbol renamed/removed in code, docs still reference old name | Doc says db.users.findByEmail(), code now exposes db.users.lookupByEmail() |
Findings emit even if the underlying feature is correct — drift between code and docs is the defect.
docs/adr/ for any decision matching the "architecturally significant" bar (provider swap, data-model change, public-contract change, security-model change).docs/migrations/<version>.md page with before/after snippets.The skill must know the toolchain per language. Detection is by file extension + framework signal.
/// <summary>...</summary>, <param>, <returns>, <exception>).Microsoft.AspNetCore.OpenApi (built-in in .NET 9) emits OpenAPI; render with Scalar / Swagger UI.<GenerateDocumentationFile>true</GenerateDocumentationFile> + treat CS1591 (missing XML comment on public type) as error for public APIs./// <summary>Creates a new user account.</summary>
/// <param name="email">Email address; must be unique.</param>
/// <param name="name">Display name.</param>
/// <returns>The created <see cref="User"/>.</returns>
/// <exception cref="ValidationException">If email is malformed.</exception>
/// <exception cref="DuplicateEmailException">If email already exists.</exception>
public async Task<User> CreateUserAsync(string email, string name) { ... }
javadoc (JDK built-in) or modern alternatives (Spring REST Docs for HTTP APIs — generates Asciidoc snippets from passing tests, guaranteeing docs match real behaviour)./** ... */ with @param, @return, @throws, @since, @deprecated.springdoc-openapi emits OpenAPI from controllers.-Xdoclint:all on the javadoc tool fails build on missing/broken doc tags./**
* Creates a new user account.
*
* @param email user's email address; must be unique and RFC 5322 compliant
* @param name display name (1–128 chars)
* @return the created {@link User}
* @throws ValidationException if {@code email} is malformed
* @throws DuplicateEmailException if {@code email} already exists
* @since 2.4
*/
public User createUser(String email, String name) { ... }
sphinx.ext.autodoc + napoleon for Google/NumPy style) or MkDocs + mkdocstrings[python] (Markdown-first, popular for FastAPI projects).ruff with D (pydocstyle) ruleset, or pydocstyle standalone. interrogate reports docstring coverage and can fail under a threshold.def create_user(email: str, name: str) -> User:
"""Create a new user account.
Args:
email: User's email address (must be unique, RFC 5322).
name: Display name (1–128 chars).
Returns:
The created User.
Raises:
ValidationError: If `email` is malformed.
DuplicateError: If `email` already exists.
"""
/** ... */ blocks with @brief, @param, @return, @retval, @warning, @since.WARN_AS_ERROR = YES in Doxyfile fails the build on undocumented public symbols./**
* @brief Create a new user record.
* @param email NUL-terminated UTF-8 email; must be non-NULL.
* @param name NUL-terminated UTF-8 display name; must be non-NULL.
* @param out Out-parameter receiving the newly-allocated user; caller owns.
* @retval 0 success
* @retval -EINVAL invalid email format
* @retval -EEXIST email already exists
*/
int user_create(const char *email, const char *name, user_t **out);
@tparam for template parameters)./// lines or /** ... */ blocks.mkdocs-doxygen / m.css for Markdown-flavoured rendering on top of Doxygen XML./// @brief Create a new user.
/// @tparam Allocator allocator type (defaults to std::allocator<User>).
/// @param email RFC 5322 email.
/// @param name display name.
/// @return std::expected<User, CreateError> — User on success, error code otherwise.
template<class Allocator = std::allocator<User>>
[[nodiscard]] std::expected<User, CreateError>
create_user(std::string_view email, std::string_view name);
@param, @returns, @throws, @deprecated, @example.@nestjs/swagger or zod-openapi + Hono/Express → OpenAPI; render with Scalar.eslint-plugin-tsdoc flags malformed tags; TypeDoc fails on missing docs when --validation.invalidLink + --validation.notDocumented are enabled./**
* Create a new user account.
*
* @param email - User's email; must be unique and RFC 5322 compliant.
* @param name - Display name (1–128 chars).
* @returns The created {@link User}.
* @throws {@link ValidationError} if email is malformed.
* @throws {@link DuplicateEmailError} if email already exists.
* @example
* ```ts
* const u = await createUser("a@b.com", "Ada");
* ```
*/
export async function createUser(email: string, name: string): Promise<User> { ... }
dbt docs generate + dbt docs serve produces a lineage graph and column-level documentation.COMMENT ON TABLE/COMMENT ON COLUMN (Postgres) or table/column comment DDL (MySQL/SQL Server). For dbt — description: fields in schema.yml.dbt-checkpoint (or dbt test) fails CI on missing model/column descriptions.# dbt — models/marts/users.yml
version: 2
models:
- name: dim_users
description: One row per user, latest values. Refreshes hourly.
columns:
- name: user_id
description: Surrogate key. Stable across email changes.
tests: [unique, not_null]
- name: email
description: Current verified email. Lower-cased, NFC-normalised.
-- Postgres native
COMMENT ON TABLE users IS 'One row per user account. PK = user_id.';
COMMENT ON COLUMN users.email IS 'Verified, lower-cased, NFC-normalised email.';
The 7-language section above is canonical. The shorter examples below are kept for skim-reading.
def create_user(email: str, name: str) -> User:
"""Create a new user account.
Args:
email: User's email address (must be unique)
name: User's display name
Returns:
The created User object
Raises:
ValidationError: If email is invalid
DuplicateError: If email already exists
"""
/**
* Create a new user account
* @param email - User's email address (must be unique)
* @param name - User's display name
* @returns The created User object
* @throws {ValidationError} If email is invalid
*/
function createUser(email: string, name: string): User { }
// CreateUser creates a new user account.
//
// It validates the email format and checks for duplicates.
// Returns the created user or an error if validation fails.
func CreateUser(email, name string) (*User, error) { }
Use the MADR (Markdown Architectural Decision Records) format. Source: adr/madr on GitHub. File path: docs/adr/NNNN-short-title.md where NNNN is a 4-digit sequence.
Minimal MADR fields (mandatory):
---
status: proposed | accepted | superseded by [ADR-NNNN](./NNNN-...md) | deprecated
date: 2026-05-19
deciders: [person, person]
---
# {short noun phrase describing the decision}
## Context and Problem Statement
{what is the issue we're seeing that is motivating this decision?}
## Considered Options
- option 1
- option 2
- option 3
## Decision Outcome
Chosen option: "{option N}", because {justification}.
### Consequences
- Good: ...
- Bad: ...
ADRs are immutable once accepted. If the decision changes: write a new ADR, set status: superseded by [ADR-...] on the old one, link both directions. Never edit an accepted ADR in place.
i++ // increment i)TODO(ticket-id): referencing a tracker, not TODO: fix later)## Documentation Update Report
### Files Updated
1. `README.md` — added Authentication section, updated env vars
2. `docs/api/users.md` — added POST /users endpoint + error codes
3. `src/services/auth.py` — docstrings on 3 public functions
4. `docs/adr/0042-switch-auth-provider.md` — new ADR (MADR format)
5. `docs/migrations/v3.md` — migration guide for renamed `getUser` → `fetchUser`
### Documentation Coverage
| Surface | Before | After | Tool |
|-------------------|--------|-------|-----------|
| Public functions | <X%> | <Y%> | interrogate / TypeDoc / Javadoc |
| API endpoints | <X%> | <Y%> | OpenAPI spec coverage |
| README sections | <X%> | <Y%> | manual checklist |
> Coverage numbers come from the project's actual docstring-coverage tool output.
> Do not hand-author percentages — surface them from the tool's report or omit the row.
### Missing / Drift Findings
- `src/utils/helpers.py:18` — `parse_iso8601` lacks docstring (kind: missing_api_doc)
- `docs/install.md` — link to `./old-setup.md` is broken (kind: broken_link)
- `docs/tutorials/getting-started.md` — code block at L42 never executed in CI (kind: untested_snippet)
- Auth-provider swap merged in PR #318 — no ADR present (kind: missing_adr)
### Changelog Entry
[markdown block sourced from changelog-generator]
Static-site generators:
| Tool | Strengths | When |
|---|---|---|
| Docusaurus (Meta) | React-based, large plugin ecosystem, native i18n + versioning | Engineering-heavy projects that already do React; want full theming control |
| MkDocs + Material theme | Python-native, dead-simple YAML config, fast | Python projects, small-to-medium docs, fastest setup |
| Mintlify | Hosted, ships AI search + analytics + OpenAPI rendering out of the box | Product teams that ship often and want managed infra |
| Astro Starlight | Fast runtime, MDX, lower opinionation than Docusaurus | Mixed JS/TS projects, MDX-heavy authors |
| Hugo | Fastest builder by far; Go-templated | Very large doc sites (thousands of pages) where build time matters |
Quality gates (must be in CI):
| Tool | Checks | Failure mode |
|---|---|---|
| lychee | Broken internal + external links | Fail build on dead link (with retry for transient 5xx) |
| markdown-link-check | Per-file link verification | Alternative to lychee in Node-only stacks |
| Vale | Prose style, terminology consistency, voice rules | Warn or error per .vale.ini severity config |
| (language-specific snippet runners) | Fenced code blocks compile/execute | Fail build on snippet error |
interrogate / TypeDoc validation / -Xdoclint:all | Public-API docstring coverage | Fail under threshold |
Data layer:
| Tool | Use |
|---|---|
| dbt docs | Lineage graph + column docs for dbt models; gate with dbt-checkpoint |
| SchemaSpy | ER diagrams + table catalog from JDBC-reachable DBs |
API / contract:
| Tool | Use |
|---|---|
| OpenAPI | Source-of-truth for HTTP APIs; render with Scalar / Redocly / Swagger UI / Mintlify |
| AsyncAPI | Same idea for event-driven / message-queue APIs |
| GraphQL SDL + graphql-doc-generator | GraphQL schemas |
ADR / decisions:
| Tool | Use |
|---|---|
MADR template (adr/madr) | Standard Markdown ADR format; full + minimal variants |
| adr-tools (npryce) | CLI scaffolding for ADR files + supersede links |
| log4brains | Web UI rendering of an ADR log; integrates with Docusaurus |
These tiers are the internal triage view used inside the human-readable report. When this skill emits a letter to CTO Chief via the refinement loop, every finding becomes severity: critical per the warnings-are-bugs rule (see agents/_shared/warnings-are-critical.md) — there is no soft tier on the wire. The triage tiers stay in the report for prioritization; the letter's severity field is always critical.
| Triage tier | Examples | Internal action |
|---|---|---|
| CRITICAL | Breaking change shipped with no migration guide; ADR-required decision merged without ADR; public API endpoint completely undocumented; broken link on landing page or install page | Fix before release |
| HIGH | Code/doc inconsistency on public API (renamed symbol still in docs); broken link inside a tutorial; untested code snippet in a quickstart | Fix in same PR / sprint |
| MEDIUM | Stale page (last-updated > 6 mo) where underlying code changed; missing docstring on a public-but-non-headline function; OpenAPI spec missing example values | Backlog; next docs sweep |
| LOW | Internal-helper docstring gaps; prose-style nits from Vale (passive voice, weasel words); cosmetic ToC ordering | Opportunistic |
When emitting a finding via the refinement loop, write the letter with these fields:
finding_id: <sha256(critic+target_file+line+kind)[:12]> # fingerprint for dedup
severity: critical # ALWAYS critical (warnings-are-bugs)
confidence: high | medium | low # high = directly observed; low = heuristic match
engine: link-checker | snippet-runner | doc-coverage | ast-diff | adr-detector | vale | manual
kind: stale_doc | broken_link | untested_snippet | missing_adr | missing_api_doc | missing_migration_guide | inconsistent_code_doc
target_file: docs/api/users.md
line: 42 # null if file-level
related_code_symbol: "src/api/users.py:create_user" # for inconsistent_code_doc / missing_api_doc
related_decision: "PR #318 — switch auth provider" # for missing_adr
last_updated: 2025-09-14 # for stale_doc; ISO 8601
message: "Public function `create_user` lacks a docstring; OpenAPI render will show empty description."
suggested_fix: |
Add Google-style docstring to src/api/users.py:create_user with Args/Returns/Raises.
Will be picked up by mkdocstrings on next build.
reference: https://diataxis.fr/reference/
confidence: low single-source findings (e.g. Vale-only style nits) do not block phase advancement on their own; two independent engines agreeing (e.g. lychee + manual review) escalate. kind: missing_migration_guide always cross-links to [[backwards-compatibility-checker]].
lychee (or equivalent) passes — no broken links-Xdoclint:all)When invoked as a critic by the Iron Loop integrator (see docs/REFINEMENT_LOOP.md), apply the warnings-are-critical rule:
severity: critical in the letter you write to CTO Chief.warn — there is no soft tier.## Decisions Taken Under Ambiguity section.The principle: a doc that's wrong today is a support ticket tomorrow and a re-architecture meeting next quarter. Code that ships green-with-broken-docs ships with known latent confusion.