SKILL DETAIL
developer-docs-structure-audit
samber/developer-relations-skills/developer-docs-structure-audit
Audits an existing developer documentation set's structure - a page-by-page inventory classified against the Diátaxis modes (tutorial, how-to, reference, explanation), mixed-mode and misplaced pages, coverage gaps per product surface, navigation drift against the file tree, a CNCF TechDocs rubric score, and a prioritized remediation queue. Use whenever the user mentions a docs structure or content audit, docs information architecture, Diátaxis, "our documentation is a mess", a docs gap analysis, what docs are missing, where a page should live, or reorganizing a documentation site - even if they only say "our docs are hard to navigate". Not for writing pages. Do NOT use for docs search ranking - use samber/developer-relations-skills@docs-seo.
Installation
npx skills add https://github.com/samber/developer-relations-skills --skill developer-docs-structure-audit
スキルファイル
SKILL.md
最終同期 · 2026/10/23
evals/evals.json›
{
"skill_name": "developer-docs-structure-audit",
"evals": [
{
"id": 1,
"prompt": "We run Kestrelpay, a payments API. Our docs are 210 pages on Docusaurus. Last month our design researcher ran a Treejack study with 180 participants on 6 core tasks against our current tree: 84% task success overall, 67% direct-path rate. The weakest task was 'find the webhook retry policy' at 52% success. Leadership has already budgeted a quarter of writer time for an information-architecture rebuild and wants me to hand them the new tree. Where do I start?",
"expected_output": "A recommendation to cancel the site-wide restructure because the tree test already passes, redirect the approved budget to gap-filling and freshness, restructure only the failing webhook branch, and drop moves and renames from the queue.",
"files": [],
"expectations": [
"States the site-wide restructure should be cancelled rather than executed, despite the budget already being approved",
"Names the threshold of roughly 80% task success and 60% direct-path rate as the line above which structure is not the bottleneck",
"Compares both reported figures (84% success, 67% direct path) against that threshold explicitly",
"Redirects the approved writer budget to gap-filling and content freshness instead of a new tree",
"Labels the 80%/60% reading as a practitioner heuristic rather than an authoritative standard",
"Notes that a borderline number would be a prompt to talk to the team, not a verdict",
"Identifies the 52% webhook-retry task as below the roughly 60% task-success line and restructures that branch only",
"Removes page moves from the remediation queue on the grounds that the tree test already passes",
"Removes section renames from the remediation queue on the same grounds",
"States explicitly which action types were deleted from the queue rather than silently omitting them",
"Warns that a restructure a tree test says is unnecessary breaks inbound links for no gain",
"Does not propose a re-platforming or a full docs rewrite",
"Keeps every structural recommendation scoped to a single branch or page rather than the whole tree"
]
},
{
"id": 2,
"prompt": "I have inherited the docs at Northwind Telemetry. It is a DITA setup in Oxygen, about 1,400 topics, all typed as concept, task or reference, and the typing is applied rigorously - the previous writer was strict about it. Our VP read about Diataxis and wants everything migrated to tutorial/how-to/reference/explanation this year. I need an audit that says what moves where. One thing support keeps repeating: new customers have nowhere to start, they get dropped straight into task topics.",
"expected_output": "An audit run against the existing DITA taxonomy rather than a conversion plan, treating the missing beginner entry point as a genuine gap because DITA has no tutorial equivalent.",
"files": [],
"expectations": [
"Recommends auditing against the site's existing DITA taxonomy rather than converting it to Diataxis",
"States that consistency of application matters more than which framework supplies the taxonomy",
"Names the conditions that would justify a switch: the declared taxonomy applied inconsistently, or leaving a whole reader need uncovered",
"Identifies the missing beginner entry point as a real gap rather than a mapping artefact, because concept/task/reference has no tutorial equivalent",
"Names DITA's three base topic types as concept, task and reference",
"Notes that later DITA versions added topic types such as general-task, troubleshooting and glossentry",
"Cites the documented precedent of a team spending months debating a single new DITA topic type before dropping it entirely",
"States that a Diataxis tutorial has a different rhetorical shape, tailored for education rather than problem-solving",
"Recommends adding a learning path or tutorial entry point rather than retyping existing topics",
"Says up front in the report which taxonomy the findings are stated against, so the VP can read them",
"Does not deliver a topic-by-topic DITA-to-Diataxis mapping table as the main output",
"Rejects the full-year migration as the recommended action"
]
},
{
"id": 3,
"prompt": "Audit is done on the Larkfield Data Cloud docs. Here is what I found: 6 pages that mix a procedure with a full option table; 1 duplicate pair (our 'Connect to Snowflake' guide exists in two places and the two now disagree on the required IAM role - it is step 3 of onboarding); 9 pages sitting in the wrong section; a missing Terraform provider tutorial (18 support tickets in the last 90 days asking for it); and 3 section names nobody understands. Constraint from the platform team: our docs are a static export behind a CDN with no redirect layer, and they will not add one this quarter. One writer, about 6 hours a week. Give me the queue.",
"expected_output": "A queue ordered by reader need fixed per hour, with splits first, the contradictory duplicate promoted, moves and renames deleted outright for lack of redirects, and the missing tutorial promoted on its ticket evidence.",
"files": [],
"expectations": [
"Orders the queue by reader need fixed per hour of effort rather than by cheapest action or by number of findings closed",
"States the ordering explicitly rather than leaving it implied by row order",
"Places splitting the 6 mixed pages ahead of merging the duplicate pair on the efficiency ordering",
"Explains that split outranks merge on efficiency because a merge blocks on someone with authority deciding which text is true, and a split does not",
"Deletes the 9 page moves from the queue entirely rather than demoting them, because the team cannot ship redirects",
"Deletes the 3 section renames from the queue entirely for the same redirect reason",
"Names explicitly which actions were deleted and why, rather than silently dropping them",
"Promotes the missing Terraform provider tutorial above its default rank and cites the 18 recurring support tickets as the promoting signal",
"States that writing a missing page otherwise loses every round under an efficiency ordering, because it is high value and high effort",
"Promotes merging the Snowflake duplicate on the grounds that the two copies give contradictory answers on the adoption path",
"Emits separate orderings for efficiency and value rather than one blended ranking",
"Caps the queue at what 6 writer-hours a week can absorb before the next re-score, and names what was deferred",
"Gives every queue item an action that ships alone and improves the docs by itself",
"Does not make building a redirect layer a prerequisite for the rest of the queue"
]
},
{
"id": 4,
"prompt": "Honestly the docs at Quarrystone (CI/CD runner, about 90 pages) are a mess and I want to rip the band-aid off. My plan: create four new top-level sections - Tutorials, How-to Guides, Reference, Explanation - wire them into the sidebar next sprint, then spend Q3 moving all 90 pages into the right one and rewriting whatever does not fit. The CEO is fine with a quarter of downtime on docs work. Sanity check me?",
"expected_output": "A refusal of both the empty four-section scaffold and the quarter-long teardown, replaced by an incremental loop of single shippable actions built on a completed inventory.",
"files": [],
"expectations": [
"Rejects creating the four empty top-level sections ahead of content that fills them",
"Gives the reason that empty structures advertise the gaps and force readers to learn a vocabulary before they can navigate",
"Rejects the Q3 teardown, stating that rewriting the docs site is an abdication rather than a recommendation",
"Requires the documentation to stay useful at every step of the remediation",
"Proposes the small remediation loop: choose something, assess it, decide the single next action that produces an immediate improvement, do it, publish, repeat",
"Requires each action to ship alone and improve the docs by itself rather than paying off only at the end of the quarter",
"Insists on a complete page inventory before any page is judged or moved",
"Does not assume the four mode names should become the navigation labels",
"Warns that moving 90 pages breaks inbound links unless a redirect accompanies each move",
"Points out that Diataxis itself rules out both the empty scaffolding and the teardown",
"Starts from findings tied to specific pages rather than from a target structure",
"Does not endorse a quarter of docs downtime"
]
},
{
"id": 5,
"prompt": "Running the classification pass on Beacon Ledger's docs. Some calls I am unsure about - tell me how to file each, and whether it is a finding. (1) reference/api/transactions.md: a big endpoint table, and the intro has one sentence explaining why transactions are immutable. (2) docs/adr/0007-event-sourcing.md through 0031: our architecture decision records, sequentially numbered, never edited after acceptance. (3) release-notes/2026-q2.md. (4) guides/upgrading-to-v4.md, which walks you through the upgrade. (5) faq.md, 40 questions, everything from pricing to a 6-step certificate rotation. (6) troubleshooting/errors.md, which lists 60 error codes and for 12 of them gives a fix procedure. (7) docs/index.md, the landing page. (8) reference/glossary.md. We are at 340 pages and I have 190 findings so far.",
"expected_output": "Correct mode calls for each hard case, the single explanatory sentence and the ADR directory left unflagged, and the 190-finding count challenged as over-flagging.",
"files": [],
"expectations": [
"Declines to report the single explanatory sentence in reference/api/transactions.md as a finding",
"States the mixing threshold: flag only when the second mode occupies roughly a fifth of the page, or contains something the reader must act on",
"Treats the ADR directory as already correctly typed and declines to flag it for not fitting the four modes",
"Classifies release-notes/2026-q2.md as reference",
"Classifies guides/upgrading-to-v4.md as a how-to guide",
"Treats the FAQ as a symptom rather than a mode, and files each answer into its real mode",
"Allows the FAQ to remain as an index if site search is weak",
"Splits troubleshooting/errors.md: reference for the enumerated error codes, how-to for the 12 entries that prescribe a fix",
"Classifies reference/glossary.md as reference",
"States that a landing page is not a mode, and judges docs/index.md on whether it routes to all four",
"Flags 190 findings on a 340-page set as over-flagging, and cuts to pages where a reader's need actually fails",
"Does not phrase any finding as a violation of Diataxis",
"Recommends recording a confidence level on borderline pages and moving on rather than debating the call"
]
},
{
"id": 6,
"prompt": "Our docs at Halyard Grid (grid-scale battery telemetry, sold to utilities - six-month procurement, security review, the works) run to 260 pages. A new head of growth looked at them and says they are bloated with theory: we have architecture overviews, a whole security-model section, published rate and retention limits, a cost model page, and a migration-from-legacy-SCADA explainer. His instruction is to cut each of those to a paragraph and push everything into quickstarts, because developers want to copy-paste, not read essays. I am supposed to produce the audit that backs that up. What does the audit actually say?",
"expected_output": "A refusal to cut the explanation content, naming audience blindness, weighting the mode mix for an enterprise evaluation motion, and protecting the evaluator content while keeping it off the getting-started path.",
"files": [],
"expectations": [
"Refuses to endorse cutting the explanation content and names audience blindness as the error being made",
"States that team and enterprise adoption needs explanation early, because an evaluator or signer who never runs the quickstart has to approve the choice",
"Names architecture, security model, limits, cost model and migration path as the explanation content enterprise buyers need",
"States that reference completeness carries procurement weight, and that missing limits or compliance detail become sales blockers",
"Settles the audience question before judging mode balance, rather than accepting the head of growth's framing",
"Recommends one entry point per audience rather than a single merged tour",
"Warns against letting evaluator content colonise the getting-started path",
"Distinguishes the self-serve individual mix (weight tutorials and how-tos, short time-to-first-success) from the enterprise mix this product actually has",
"Does not recommend deleting or shrinking the architecture overview, security-model section or cost-model page",
"Judges mode balance against the stated buyer rather than a generic developer persona",
"States that mode balance judged against the wrong audience produces confident, wrong recommendations",
"Proposes a separate self-serve entry point if individual developers are also an audience, rather than converting existing explanation pages"
]
},
{
"id": 7,
"prompt": "I need to hand our board a number for docs quality at Pinerock (open-source workflow engine, 120 docs pages, two maintainers, no writer). They want something defensible, not 'the docs feel bad'. What do I score and how? On my first pass I gave us 4s across the board, because honestly the writing is decent.",
"expected_output": "A two-layer scoring approach: the published CNCF TechDocs 1-5 rubric per section for the external number, plus a separately agreed structural scorecard, with the straight 4s challenged against published calibration.",
"files": [],
"expectations": [
"Recommends the CNCF TechDocs rubric for the rating that travels outside the docs team",
"States the rubric's named 1-to-5 scale: 1 not present, 2 needs improvement, 3 meets standards, 4 meets or exceeds standards, 5 exemplary",
"Names the Project documentation criteria: information architecture, new user content, content maintainability, content creation processes, inclusive language",
"Scores each top-level docs section rather than issuing a single overall number",
"Challenges the straight 4s, stating that a first audit returning them usually means the rubric was applied too generously",
"Gives the published calibration for a serious open-source project with no dedicated writer: mostly 1s and 2s on entry-point and process criteria, 3s where a maintainer culture already exists",
"Adds a second, structural scorecard computed from the inventory, kept distinct from the rubric rating",
"Labels the CNCF 1-5 scale as published and the structural scorecard's pass marks as a self-set baseline",
"Requires agreeing the scorecard thresholds with the user before scoring rather than importing them silently",
"Names concrete scorecard measures with targets, such as mode purity at or above 90%, navigation depth of 3 or less, zero orphans, staleness at or below 10%",
"Reports the ROT rate without grading it against a target",
"States the audit is unfinished while any must-fix measure fails, and requires re-running the inventory and re-scoring after each remediation batch to report the delta",
"Scores contributor documentation only if the user asks for it, rather than folding it into the headline number"
]
},
{
"id": 8,
"prompt": "Vendor situation at Corvid Streams: our docs run on Mintlify, but the content repo belongs to the agency that built the site and they will not grant access this quarter. All I can reach is the public site and our analytics property. Roughly 480 pages. I still need the full audit with a scorecard by the 30th. How much of this can I actually do?",
"expected_output": "An evidence-scoped audit: sitemap-versus-nav diff for orphan candidates, staleness and orphan measures dropped from the scorecard rather than estimated, inventory labelled nav-only, recommendations downgraded to proposed.",
"files": [],
"expectations": [
"Fixes the evidence scope before promising measures, stating that a live site yields the rendered navigation and the sitemap only",
"Diffs sitemap.xml against the rendered navigation to produce orphan candidates",
"Names Mintlify's navigation source as the navigation key in docs.json, with mint.json on older projects",
"Notes that anything unlisted in a Mintlify navigation is unreachable",
"Drops the staleness measure from the scorecard rather than estimating it, because last-modified dates are not visible",
"Drops the orphan measure from the scorecard as well, because drafts, hidden pages and front matter cannot be seen",
"States in the report which measures were dropped and why",
"Labels the inventory as nav-only",
"Downgrades structural recommendations from validated to proposed, since no user testing is available",
"Substitutes top 404s, zero-result site searches and high-exit landing pages as partial signals",
"Does not report an orphan count or a staleness percentage as if it had been measured"
]
},
{
"id": 9,
"prompt": "Built the coverage matrix for Almsley Robotics' developer docs. Surfaces down the side: Python SDK, C++ SDK, ROS 2 bridge, Fleet API, on-prem deployment, Grafana integration. Modes across the top. I count 14 empty cells. Signals I can reach: docs site search through Algolia, our GitHub issues, and page analytics. Our /api/fleet/overview page has a 78% exit rate, the highest on the site. I want all 14 missing pages in the backlog and writing started Monday - which order?",
"expected_output": "Empty cells treated as candidates, each confirmed against a demand signal before entering the queue, unevidenced gaps moved to a question list, and the high exit rate not read as a gap on its own.",
"files": [],
"expectations": [
"Treats the 14 empty cells as candidate gaps, not confirmed ones",
"Requires each candidate gap to be confirmed against a named demand signal before it enters the queue",
"Puts any gap with no evidence on a list of questions for the team rather than into the work queue",
"Attaches the supporting evidence to each gap that does enter the queue",
"States that a full grid is not the target, and that a minor surface may legitimately need only reference plus one how-to",
"Ranks gaps by evidence volume against adoption impact rather than by how large the hole looks in the matrix",
"Declines to treat the 78% exit rate on /api/fleet/overview as a gap on its own, noting a high-exit page can mean the reader found the answer and left",
"Pairs the exit-rate reading with a support-ticket trend or a satisfaction prompt before logging it as a gap",
"Names zero-result site searches as the signal that proves a missing page in the user's own words, and maps it to the Algolia analytics available",
"Names repository issues labelled question, support or docs as public, quotable evidence for prioritization",
"States that one good tutorial per audience is usually enough, rather than one per surface",
"Identifies an empty reference cell on a surface users configure as the most damaging gap type"
]
},
{
"id": 10,
"prompt": "Second time around for us. We reorganised Tessellate Maps' docs into Diataxis in early 2025 - big effort, everyone agreed it came out better. Eighteen months later it has drifted right back: procedures in the concepts section, four pages that are clearly reference filed under tutorials, and two copies of the routing-profiles doc. Same six engineers write the docs, no writer, no docs CI. What do I do differently this time?",
"expected_output": "A diagnosis of the recurrence as organisational rather than structural, a maturity read, and the governance and drift-control layer put ahead of further page surgery and shipped inside the queue.",
"files": [],
"expectations": [
"Diagnoses the recurrence as organisational rather than structural",
"Places the governance layer ahead of further page surgery",
"Applies a documentation maturity read and names Hackos's Information Process Maturity Model",
"Names its five levels: ad hoc, rudimentary, organized and repeatable, managed and sustainable, optimizing",
"States that a team at ad hoc or rudimentary has no repeatable process, so any structural fix decays",
"Says this explicitly in the report, not only in the recommendations",
"Recommends declaring the content type in front matter and validating it in CI, so a type/content mismatch becomes a build failure rather than an audit finding years later",
"Recommends shipping page templates so contributors fill blanks instead of inventing structure",
"Recommends prose and link checking in CI, naming tools such as Vale, markdownlint and lychee",
"Recommends CODEOWNERS per subtree so each subtree has named reviewers",
"Requires a redirect for every moved URL and sets a re-audit cadence of once a quarter",
"Ships the drift controls as part of the remediation queue rather than as a follow-up project"
]
},
{
"id": 11,
"prompt": "I maintain Ferrite, a Rust actor framework, about 4k stars, with a CNCF sandbox application in flight. The docs are whatever contributors wrote - roughly 70 pages on mdBook. There is no writer and there will never be budget for one: it is me and two part-timers working evenings. Can you audit the structure?",
"expected_output": "The audit run as an interim measure, alongside a routing to the free external documentation-analysis programs and a queue sized for an engineer-only evening team.",
"files": [],
"expectations": [
"Runs the audit and additionally tells the user that a free external analysis is available",
"Names the CNCF TechDocs assistance program as one source of that external analysis",
"Names Google Season of Docs as the other",
"States that either program delivers an analysis, an implementation plan and an issues backlog",
"States that either external program beats a solo generalist pass",
"Frames this audit as the interim measure while the user applies",
"Pushes writing-heavy actions down the queue because the remediation team is engineer-only",
"Assigns structural ownership to maintainers through CODEOWNERS and pull-request review, since no writer exists",
"Names the three failure modes of a solo generalist pass: treating it as a one-off friction log, optimising only the hero getting-started path, and skipping user validation",
"Splits the deliverable into a report, an implementation plan and a set of tickets contributors can pick up",
"Sizes the queue against the stated evenings-and-part-timers capacity rather than a full-time writer's"
]
},
{
"id": 12,
"prompt": "Here is our tree, classify it:\n\ndocs/\n intro.md\n getting-started/{install.md, first-pipeline.md, concepts.md}\n guides/ (31 files)\n api/ (auto-generated, 210 files)\n architecture/{overview.md, scheduler.md, storage.md}\n faq.md\n\nIt is Docusaurus. Go ahead and give me the four-quadrant classification for all of them.",
"expected_output": "A refusal to classify before the gating interview questions are answered, asked one at a time, followed by a complete inventory pass with the Docusaurus navigation sources and the triage rule named.",
"files": [],
"expectations": [
"Declines to classify any page before the gating questions are answered",
"Asks where the docs live and whether the repository itself is readable",
"Asks who reads the docs - self-serve individual developers, engineering teams behind a contract, or both - and which ecosystems or languages",
"Asks what triggered the audit: a support pattern, a launch, a migration, a complaint, or a routine review",
"Asks one question at a time rather than presenting the whole list at once",
"Asks whether any part of the docs is out of scope, naming the auto-generated API reference as a candidate",
"Asks about redirect and URL-stability constraints before classification, because they change which actions can enter the queue",
"Asks what date the remediation has to show a result by, because it re-ranks the queue",
"Builds the complete inventory before making any qualitative judgement, keeping inventory and audit as distinct passes",
"Offers to run the bundled inventory script over the docs tree with the navigation config passed in",
"Names Docusaurus's navigation sources as sidebars.js or sidebars.ts and _category_.json, and notes that autogenerated sidebars follow the folder tree and front-matter sidebar_position",
"Names the triage rule for which pages to open in full: every page on the adoption path, every page above roughly 2,500 words, every page combining steps with an option table, plus a sample of the rest"
]
},
{
"id": 13,
"prompt": "Write up the audit for Stagpath Analytics. Findings I have: the Guides landing page lists 41 ungrouped links (14 conceptual, 27 procedures) and site search shows 'how to' queries landing there with a 71% exit rate. concepts/access-control.md has a permissions diagram, then 9 numbered steps to add a service account, then a 30-row permission table, and it is our number two search landing page. The Node SDK has 7 how-tos and an API reference but no quickstart, and site search shows 'node getting started' at 260 queries in 90 days with 0 results. Separately, a bunch of our Go code samples do not compile any more. Our Reference section is genuinely well organised. Format it the way you would hand it to a VP.",
"expected_output": "A report with a three-sentence verdict, findings in the Now / Reader impact / Next action format with severity tiers and the user's own figures, the broken samples pushed out of scope with an owner, and the clean Reference section credited.",
"files": [],
"expectations": [
"Opens with a verdict of roughly three sentences covering the shape of the problem, its single biggest cost, and the size of the fix",
"Writes each finding in the Now / Reader impact / Next action format, with a severity tag and the page path",
"Assigns severities from the three tiers: must fix, should fix, worth noting",
"Rates concepts/access-control.md and the missing Node quickstart as must fix, since both sit on a common reader's path",
"Gives each finding exactly one next action, doable in one sitting",
"Carries the user's own figures into the findings: 41 links, 71% exit rate, 9 steps, 30-row table, 260 zero-result queries",
"Phrases every finding as a reader failing to get something, never as a framework violation",
"Recommends extracting the 9 service-account steps into their own how-to, with the concept page linking to it, rather than restructuring the concepts section",
"Fixes the Guides landing page by grouping its links on that page only, with no files moved",
"Moves the non-compiling Go samples out of scope, noting them separately with a named owner rather than as a structural finding",
"Gives credit to the Reference section for already being clean",
"Includes a section for what the audit did not cover, and an inputs section stating what was inventoried, which signals were available and what was inferred"
]
}
],
"trigger_queries": [
{ "query": "audit the structure of our developer docs", "should_trigger": true },
{ "query": "our documentation is a mess, can you help", "should_trigger": true },
{ "query": "run a Diataxis audit on our docs site", "should_trigger": true },
{ "query": "which of our docs pages are in the wrong section?", "should_trigger": true },
{ "query": "what docs are we missing?", "should_trigger": true },
{ "query": "do a docs gap analysis", "should_trigger": true },
{ "query": "where should this page live in our docs?", "should_trigger": true },
{ "query": "our docs are hard to navigate", "should_trigger": true },
{ "query": "reorganize our documentation site", "should_trigger": true },
{ "query": "docs information architecture review", "should_trigger": true },
{ "query": "classify our documentation pages into tutorial, how-to, reference and explanation", "should_trigger": true },
{ "query": "content audit of our docs", "should_trigger": true },
{ "query": "we have 300 docs pages and nobody can find anything", "should_trigger": true },
{ "query": "score our documentation against the CNCF techdocs rubric", "should_trigger": true },
{ "query": "is our docs navigation lying about what is in each section?", "should_trigger": true },
{ "query": "find the orphan pages in our documentation", "should_trigger": true },
{ "query": "our getting started section is full of reference tables, what do we do", "should_trigger": true },
{ "query": "help me build a coverage matrix for our docs", "should_trigger": true },
{ "query": "should we restructure our docs or not?", "should_trigger": true },
{ "query": "we ran a tree test on our docs, now what", "should_trigger": true },
{ "query": "build a remediation queue for our documentation", "should_trigger": true },
{ "query": "how do I prioritize fixing our docs structure", "should_trigger": true },
{ "query": "support keeps answering the same question over and over - is that a docs gap", "should_trigger": true },
{ "query": "inventory every page in our docs and tell me what is wrong", "should_trigger": true },
{ "query": "we are on Docusaurus and the sidebar does not match the folders", "should_trigger": true },
{ "query": "our docs have no obvious starting point for new users", "should_trigger": true },
{ "query": "half our pages are trying to do two jobs at once", "should_trigger": true },
{ "query": "split our mixed documentation pages", "should_trigger": true },
{ "query": "audit our mkdocs site structure", "should_trigger": true },
{ "query": "we use DITA, should we move to Diataxis?", "should_trigger": true },
{ "query": "our docs decayed back into a mess 18 months after we fixed them", "should_trigger": true },
{ "query": "which docs sections should we merge?", "should_trigger": true },
{ "query": "review our documentation taxonomy", "should_trigger": true },
{ "query": "tell me which of our doc pages are redundant, outdated or trivial", "should_trigger": true },
{ "query": "docs ROT analysis", "should_trigger": true },
{ "query": "we want a defensible score for docs quality to show the board", "should_trigger": true },
{ "query": "my VP wants to rewrite the whole docs site - talk me into it or out of it", "should_trigger": true },
{ "query": "card sort and tree test for our documentation", "should_trigger": true },
{ "query": "how deep should our docs navigation go?", "should_trigger": true },
{ "query": "our FAQ page has grown to 40 questions, what do we do with it", "should_trigger": true },
{ "query": "do we need a tutorial for every SDK?", "should_trigger": true },
{ "query": "our docs work for enterprise buyers but not for self-serve devs", "should_trigger": true },
{ "query": "where do release notes belong in our docs structure?", "should_trigger": true },
{ "query": "should troubleshooting pages be how-tos or reference?", "should_trigger": true },
{ "query": "audit the layout of our knowledge base for a dev tool", "should_trigger": true },
{ "query": "why do people keep landing on the wrong page in our docs", "should_trigger": true },
{ "query": "we have two copies of the same guide and they disagree", "should_trigger": true },
{ "query": "our docs site search returns nothing for half the queries people type", "should_trigger": true },
{ "query": "plan a documentation restructure without breaking links", "should_trigger": true },
{ "query": "what governance do we need so our docs structure does not drift again", "should_trigger": true },
{ "query": "we have no technical writer - how do we fix how our docs are organized", "should_trigger": true },
{ "query": "map out our documentation hierarchy and tell me what is broken about it", "should_trigger": true },
{ "query": "we are at 900 pages and growing, will our current sections survive", "should_trigger": true },
{ "query": "our Concepts folder is full of procedures", "should_trigger": true },
{ "query": "produce an information architecture report for our API docs", "should_trigger": true },
{ "query": "how do I tell whether a page is a tutorial or a how-to?", "should_trigger": true },
{ "query": "our docs nav has sections with only one page in them", "should_trigger": true },
{ "query": "evaluate whether our documentation covers every product surface", "should_trigger": true },
{ "query": "what should be in the docs backlog next quarter", "should_trigger": true },
{ "query": "our docs got terrible scores in a user survey, where do I start", "should_trigger": true },
{ "query": "review our documentation hierarchy before we migrate platforms", "should_trigger": true },
{ "query": "the same concept is called three different things across our docs", "should_trigger": true },
{ "query": "do a page-by-page review of our docs and tell me what to move", "should_trigger": true },
{ "query": "how many of our docs pages are single-mode?", "should_trigger": true },
{ "query": "our onboarding docs and our reference docs are the same pages", "should_trigger": true },
{ "query": "identify the entry points missing from our documentation", "should_trigger": true },
{ "query": "audit the structure of our SDK documentation set", "should_trigger": true },
{ "query": "what do we measure after a docs reorg to prove it worked", "should_trigger": true },
{ "query": "a customer said they could not find the rate limits page - is that a structure problem", "should_trigger": true },
{ "query": "check whether our docs sidebar matches the file tree", "should_trigger": true },
{ "query": "our Sphinx build warns about pages outside every toctree", "should_trigger": true },
{ "query": "help me decide what documentation to write next based on what is missing", "should_trigger": true },
{ "query": "write a quickstart for our Python SDK", "should_trigger": false },
{ "query": "our quickstart takes 40 minutes, make it shorter", "should_trigger": false },
{ "query": "write a tutorial teaching our streaming API", "should_trigger": false },
{ "query": "review this tutorial for pacing and checkpoints", "should_trigger": false },
{ "query": "turn these support tickets into troubleshooting pages", "should_trigger": false },
{ "query": "write an error reference page for our 4xx codes", "should_trigger": false },
{ "query": "our docs do not rank on Google for 'rate limiting'", "should_trigger": false },
{ "query": "fix canonicals and hreflang across our versioned docs", "should_trigger": false },
{ "query": "set up redirects so our docs stop losing search rankings", "should_trigger": false },
{ "query": "our docs pages are not getting indexed", "should_trigger": false },
{ "query": "make our docs readable by coding agents", "should_trigger": false },
{ "query": "should we publish an llms.txt for our documentation?", "should_trigger": false },
{ "query": "our OpenAPI spec is incomplete - fix the machine-readable entry points", "should_trigger": false },
{ "query": "define the policy every code sample in our docs has to meet", "should_trigger": false },
{ "query": "audit our docs code samples, half of them do not run", "should_trigger": false },
{ "query": "rewrite our repository README", "should_trigger": false },
{ "query": "audit the README of our open source project", "should_trigger": false },
{ "query": "turn this release's commits into changelog entries", "should_trigger": false },
{ "query": "write release notes developers will actually read", "should_trigger": false },
{ "query": "write the migration guide for our v3 to v4 breaking changes", "should_trigger": false },
{ "query": "document what breaks in the next major version", "should_trigger": false },
{ "query": "which technical keywords should our docs target", "should_trigger": false },
{ "query": "mine our docs search logs for keyword opportunities", "should_trigger": false },
{ "query": "map the developer journey from discovery to advocacy", "should_trigger": false },
{ "query": "build a stage-by-stage developer journey map with owners", "should_trigger": false },
{ "query": "is our API reference complete?", "should_trigger": false },
{ "query": "grade the prose quality of our generated API reference", "should_trigger": false },
{ "query": "write an engineering blog post about our new scheduler", "should_trigger": false },
{ "query": "cut our developer audience into named segments", "should_trigger": false },
{ "query": "design our developer education program and certification", "should_trigger": false },
{ "query": "plan a quarter of devrel content", "should_trigger": false },
{ "query": "what devrel metrics should we report to the board", "should_trigger": false },
{ "query": "instrument our docs with an event taxonomy and a tracking plan", "should_trigger": false },
{ "query": "design our developer community's code of conduct", "should_trigger": false },
{ "query": "audit our CONTRIBUTING file and the path to a first merged pull request", "should_trigger": false },
{ "query": "set up issue triage labels and response targets for our repo", "should_trigger": false },
{ "query": "choose a license for our open source project", "should_trigger": false },
{ "query": "benchmark a competitor's developer relations motion", "should_trigger": false },
{ "query": "write a case study about a customer's production deployment", "should_trigger": false },
{ "query": "prepare me for a podcast interview about our product", "should_trigger": false },
{ "query": "outline my accepted conference talk", "should_trigger": false },
{ "query": "script a screencast about our CLI", "should_trigger": false },
{ "query": "optimize our GitHub organization profile", "should_trigger": false },
{ "query": "run an information architecture review of our marketing website", "should_trigger": false },
{ "query": "restructure the navigation of our ecommerce site", "should_trigger": false },
{ "query": "audit our website", "should_trigger": false },
{ "query": "on-page SEO audit for our landing pages", "should_trigger": false },
{ "query": "run a Lighthouse performance audit", "should_trigger": false },
{ "query": "do a security audit of this repository", "should_trigger": false },
{ "query": "design audit of our dashboard UI", "should_trigger": false },
{ "query": "audit our content quality for tone and grammar", "should_trigger": false },
{ "query": "write docstrings for these Python functions", "should_trigger": false },
{ "query": "generate documentation from my codebase", "should_trigger": false },
{ "query": "look up the Convex docs for me", "should_trigger": false },
{ "query": "find the right page in the AWS documentation", "should_trigger": false },
{ "query": "translate our mkdocs site into Japanese", "should_trigger": false },
{ "query": "convert these Word documents to markdown", "should_trigger": false },
{ "query": "set up a docs pipeline that publishes on merge", "should_trigger": false },
{ "query": "write an architecture decision record for our event sourcing choice", "should_trigger": false },
{ "query": "review this design doc", "should_trigger": false },
{ "query": "our Confluence space is a mess, reorganize it", "should_trigger": false },
{ "query": "reorganize our internal engineering wiki for employees", "should_trigger": false },
{ "query": "proofread our documentation for grammar and style", "should_trigger": false },
{ "query": "set up Vale in our CI pipeline", "should_trigger": false },
{ "query": "run a link checker over our site and fix the 404s", "should_trigger": false },
{ "query": "write a style guide for our technical writers", "should_trigger": false },
{ "query": "pick a docs generator: MkDocs, Docusaurus or Sphinx?", "should_trigger": false },
{ "query": "set up Docusaurus versioning for our v2 release", "should_trigger": false },
{ "query": "improve the accessibility of our docs site", "should_trigger": false },
{ "query": "measure how healthy our developer community is", "should_trigger": false },
{ "query": "plan our developer conference sponsorship", "should_trigger": false },
{ "query": "write the copy for our pricing page", "should_trigger": false }
]
}
references/audit-report-template.md›
# Audit report shape
## Table of Contents
- [Template](#template)
- [Verdict](#verdict)
- [Section ratings](#section-ratings)
- [Scorecard](#scorecard)
- [Coverage matrix](#coverage-matrix)
- [Findings](#findings)
- [Remediation queue](#remediation-queue)
- [Not covered by this audit](#not-covered-by-this-audit)
- [Inputs](#inputs)
- [Finding format](#finding-format)
- [Severity tiers](#severity-tiers)
- [Filled excerpt](#filled-excerpt)
- [Verdict](#verdict)
- [Findings](#findings)
- [Remediation queue](#remediation-queue)
- [Negative example - findings that should never ship](#negative-example-findings-that-should-never-ship)
- [Delivery rules](#delivery-rules)
## Template
```markdown
# Docs structure audit - <product>, <date>
## Verdict
<Three sentences: the shape of the problem, the single biggest cost it creates, the size of the fix.>
## Section ratings
| Section | Information architecture | New user content | Content maintainability | Content creation processes |
| -------------------------------------------------------------------------------------------------- | ------------------------ | ---------------- | ----------------------- | -------------------------- |
| Guides | 2 | 1 | 3 | 1 |
| ... |
| <1 = not present, 2 = needs improvement, 3 = meets standards, 4 = meets or exceeds, 5 = exemplary> |
## Scorecard
| Measure | Now | Target | Threshold source | Status |
| ----------- | --- | ------ | ---------------- | ------ |
| Mode purity | 61% | ≥ 90% | agreed baseline | fail |
| ... |
## Coverage matrix
<surfaces × four modes, gaps marked>
## Findings
<one block per finding, must-fix first>
## Remediation queue
<ordered by reader need fixed per hour of effort - see SKILL.md Step 8>
| # | Action | Page(s) | Mode outcome | Reader need fixed | Effort | Evidence |
| --- | ------ | ------- | ------------ | ----------------- | ------ | -------- |
## Not covered by this audit
<accuracy, prose style, SEO, sample runnability - and who owns each>
## Inputs
<what was inventoried, which signals were available, what was inferred>
```
## Finding format
```
[severity] <page path>
- Now: <what the page mixes, misplaces, or lacks - with the evidence: heading names, step counts, table>
- Reader impact: <who arrives here with which need and leaves without it>
- Next action: <one action, doable in one sitting>
```
One action per finding. A finding whose action is "restructure the docs" is not a finding; split it until each part is a single move.
## Severity tiers
- **Must fix** - a reader with a common need cannot succeed: no entry point for a primary audience, a surface with no reference, a mixed page on the adoption path, orphaned pages that only search can reach.
- **Should fix** - the need is met but expensively: mixed pages off the main path, how-tos filed as concepts, duplicated content diverging between two locations.
- **Worth noting** - hygiene: single-page nav sections, depth beyond three levels, stale pages, titles that do not match their mode.
## Filled excerpt
```markdown
## Verdict
The docs are three how-to collections and an API dump: 47 of 78 pages inform action, and every page
that explains the system is inside a procedure. New users have no supported first path, and evaluators
have nothing to read before committing. Roughly 12 page splits and one new tutorial close the gap;
no re-platforming is needed.
## Findings
[must fix] docs/concepts/authentication.md
- Now: token-lifecycle diagram (explanation), then 8 numbered rotation steps, then a 22-row scope table.
Three modes on one URL; the page is the #2 landing page from search.
- Reader impact: someone rotating a key mid-incident scrolls past a diagram; someone evaluating the
security model hits procedure noise and leaves.
- Next action: extract the 8 steps into guides/rotate-an-api-key.md and link it from the concept page.
[must fix] no entry point for the Python SDK
- Now: the Python SDK has 6 how-tos and an API reference, no tutorial or quickstart. Site search shows
"python getting started" at 214 queries in 90 days with 0 results.
- Reader impact: the largest ecosystem in the product has no supported first hour.
- Next action: write a single-path quickstart to the first successful API call; keep alternatives out.
[should fix] docs/guides/webhooks.md
- Now: starts by installing the CLI and creating an account, then forks four ways on framework.
- Reader impact: competent readers wade through setup; beginners hit branches they cannot judge.
- Next action: replace the setup section with a prerequisites line linking the quickstart.
## Remediation queue
| # | Action | Page(s) | Mode outcome | Reader need fixed | Effort | Evidence |
| --- | ---------------------------------- | -------------------------- | -------------------- | ------------------------------------------- | ------ | -------------------------------- |
| 1 | Split rotation steps into a how-to | concepts/authentication.md | explanation + how-to | rotating a key stops needing a concept page | 1h | 214 zero-result searches |
| 2 | Trim setup from webhooks guide | guides/webhooks.md | how-to | the guide stops re-teaching setup | 30m | ticket cluster "webhook 401" |
| 3 | Write Python quickstart | new: tutorials/python.md | tutorial | Python adopters get a first-run path | 1d | 31 tickets - promoted above rank |
```
## Negative example - findings that should never ship
```markdown
[must fix] Site-wide
- Now: the documentation does not follow Diátaxis.
- Reader impact: poor developer experience.
- Next action: restructure the docs site around the four modes in Q3.
```
Three separate defects, each common and each tempting:
- The evidence is a framework name rather than an observation about a page.
- The impact is a slogan nobody can disagree with or act on.
- The action is a quarter-long project that pays off only at the end, and it is the teardown Diátaxis explicitly warns against.
The same underlying problem, written so a maintainer can pick it up before lunch:
```markdown
[must fix] docs/guides/index.md
- Now: the Guides landing page lists 34 links with no grouping; 11 are conceptual, 23 are procedures.
Site search shows "how to" queries landing here at a 71% exit rate.
- Reader impact: someone arriving with a task scans 34 undifferentiated links and leaves for search.
- Next action: split the list into "Tasks" and "Concepts" groups on this page only; no files move.
```
## Delivery rules
- Order the queue by the Step 8 ranking, say in the report that it is a ratio and not a severity list, and mark any row promoted above its rank with the signal that promoted it.
- Cap the queue at what the team can absorb before the next re-score, then say what was deferred.
- Give credit where a section is already clean; an audit that reports only failures gets read as an attack on whoever wrote the docs.
references/diataxis-classification.md›
# Classifying documentation pages
## The compass
Two questions decide any page. Answer them about the page's _dominant_ content, not its title.
| If the content… | …and serves the user's… | …then it belongs to… |
| ----------------- | ---------------------------- | -------------------- |
| informs action | acquisition of skill (study) | tutorial |
| informs action | application of skill (work) | how-to guide |
| informs cognition | application of skill (work) | reference |
| informs cognition | acquisition of skill (study) | explanation |
Tie-breaker for reference versus explanation: would someone open this _while working_, or after stepping away from the work? Reference is consulted mid-task and is usually "boring and unmemorable"; explanation is read away from the keyboard.
Tie-breaker for tutorial versus how-to: does the page promise learning, or a finished task?
- A tutorial takes a beginner down one managed path in a contrived setting and guarantees success.
- A how-to assumes competence, forks on real-world variables, and hands responsibility to the reader.
## Acceptance criteria per mode
- **Tutorial**
- One linear path, no branching, no alternatives.
- Every command produces stated visible output.
- No configuration menus.
- No "why" digressions longer than a sentence.
- Ends at a working artefact the reader built.
- **How-to guide**
- Titled with the goal ("Rotate an API key", not "API keys").
- Assumes prerequisites instead of teaching them.
- Branches where reality branches.
- May state its limits.
- Does not explain the machinery it drives.
- **Reference**
- Mirrors the shape of the product (one section per command/endpoint/setting/class).
- Consistent field order.
- Complete over readable.
- Examples are illustrative one-liners, never walkthroughs.
- No persuasion, no tutorials embedded.
- **Explanation**
- Titled around a topic or question ("Why the scheduler retries", "Architecture overview").
- Admits alternatives and trade-offs.
- Safe to skip for someone mid-task.
- Contains no required steps a reader must execute.
## Mixing symptoms and their fix
| Symptom in the page | What it really is | Default fix |
| ------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------- |
| Numbered steps followed by a full option table | how-to plus reference | Move the table to reference, link to it |
| Steps interrupted by three paragraphs of rationale | tutorial plus explanation | Pull the rationale into an explanation page, leave one sentence and a link |
| "If you use Postgres, do X instead" inside a beginners' walkthrough | how-to wearing a tutorial's title | Split: keep one supported path in the tutorial, move variants to how-tos |
| A how-to that starts at "install the CLI" | tutorial or quickstart | Replace the setup block with a prerequisites line linking the quickstart |
| API page with long narrative before the signature | reference plus explanation | Cut the narrative to one sentence, link the concept page |
| "Concepts" page that ends with a setup procedure | explanation plus how-to | Extract the procedure into its own how-to |
| One page holding install, tour, API table and FAQ | all four | Split by mode first, worry about naming second |
Small crossings are normal and healthy; the mixing threshold is in SKILL.md Step 3.
## Worked examples
**Good classification.** Page `deploy-to-kubernetes.md`: title states a goal, assumes a running cluster, branches on ingress controller, no product tour, links to the Helm values table instead of restating it. Informs action, serves work → **how-to guide**, correctly placed under "Guides". No finding.
**Misplaced page.** Page `concepts/authentication.md`: a token-lifecycle diagram (explanation), eight numbered steps to rotate a key (how-to), then a table of every scope (reference). Three modes, three audiences, one URL. Finding: split into `concepts/authentication.md` (keep the lifecycle), `guides/rotate-an-api-key.md`, `reference/scopes.md`; nav gets the two new pages, the concept page keeps links to both.
**Negative example - over-classification.** Reporting "this reference page contains one explanatory sentence" as a finding. That sentence is doing its job. Reserve findings for pages where a reader arrives with one need and meets another.
## When the site already runs another taxonomy
- **DITA** (OASIS XML standard): base topic types are `concept` ("What is…?"), `task` ("How do I…?") and `reference` (specifications, commands, parameters, error codes). DITA 1.2 added `general-task` to ease migration of legacy content; 1.3 added `troubleshooting` and `glossentry`. Three Diátaxis quadrants map onto DITA types, but a Diátaxis tutorial has, in Tom Johnson's reading, "a different rhetorical shape tailored for education rather than solving problems". DITA has no direct equivalent, so a DITA site with no learning path is a real gap, not a mapping artefact.
- **Every Page is Page One** (Mark Baker): every topic must stand alone because any page can be the reader's first. Its seven characteristics:
- Self-contained.
- Specific and limited purpose.
- Conform to a type.
- Establish their context.
- Assume a qualified reader.
- Stay on one level.
- Link richly.
Baker explicitly rejects generic typing: "The type of an EPPO topic is not something generic like concept, task, or reference, but more specific and related to the specific subject matter." A maintainer who has read Baker and dropped generic types has a defensible position; audit their pages on self-containment and context-setting instead.
- **Microsoft Learn content types**: conceptual, how-to, tutorial, reference, quickstart, declared in front matter via `ms.topic`. Audit the declaration against the content - a mismatch is a machine-checkable finding.
- **The Good Docs Project templates** follow the Diátaxis types directly, so they combine with this audit rather than competing with it.
- **Single-type conventions slot inside a taxonomy, they do not replace one.** An ADR directory (`docs/adr/`, sequential numbering, immutable once accepted, superseded ADRs pointing forward) or a Standard Readme file is already correctly typed. Do not flag it for not fitting the four-quadrant split.
Two sourced cautions apply before recommending a taxonomy change:
- Practitioners converge on structure mattering more than which framework supplies it: a Markdown system with consistent templates plus a named framework reaches DITA's structural benefits "without the XML complexity".
- Taxonomy invention has a documented cost. Paligo records a team that "spent months debating a single new DITA topic type for 'troubleshooting' content… It was finally dropped entirely, and the team resorted to basic topic types with writing guidelines, achieving the same results without the XML complexity."
Sources: OASIS DITA 1.0/1.3 specifications; everypageispageone.com; idratherbewriting.com; learn.microsoft.com; thegooddocsproject.dev; Paligo; docsbydesign.com.
## Hard cases
- **Release notes / changelog**: reference (consulted at work, describes the machinery's history). Migration guides that walk through upgrading are how-to guides.
- **FAQ**: usually a symptom, not a mode - each entry belongs to a real mode. Keep the FAQ as an index if search is weak, and file the answers properly.
- **Glossary**: reference.
- **Troubleshooting / error pages**: how-to when they prescribe a fix, reference when they enumerate error codes. Split when both.
- **Auto-generated API docs**: reference by construction; audit their completeness and entry points, not their prose.
- **Tutorial series**: acceptable as long as each part keeps a single path and the series has one entry point.
- **Landing / index pages**: not a mode - judge them on whether they route to all four.
references/docs-platform-nav-sources.md›
# Where the page list and the navigation live
## Navigation source per generator
The file tree gives you the pages; the generator's config gives you the intended navigation. Comparing the two is what exposes orphans and dead entries.
| Generator | Navigation source | Notes |
| ---------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------- |
| MkDocs / Material | `mkdocs.yml` → `nav:` | A bare directory entry (`user-guide/`) pulls in everything below it |
| Docusaurus | `sidebars.js` / `sidebars.ts`, `_category_.json` | `autogenerated` sidebars follow the folder tree and front-matter `sidebar_position` |
| Sphinx / Read the Docs | `toctree` directives from `index.rst` | Pages outside every toctree raise build warnings - read the build log |
| VitePress | `.vitepress/config.*` → `themeConfig.sidebar` | Sidebar keyed by URL prefix |
| Mintlify | `docs.json` → `navigation` (older: `mint.json`) | Explicit list; anything unlisted is unreachable |
| Astro Starlight | `astro.config.*` → `starlight({ sidebar })` | Supports autogenerate per directory |
| Nextra | `_meta.json` per folder | Order and titles both live here |
| GitBook | `SUMMARY.md` | The summary _is_ the nav |
| Docsify | `_sidebar.md` | Per-folder sidebars possible |
| Hugo / Docsy | front-matter `weight`, section `_index.md` | No central nav file; order is distributed |
| Jekyll / Just the Docs | `_data/navigation.yml` or front-matter `nav_order` | Mixed sources are common |
Front matter matters as much as the config in several of these: `sidebar_position`, `nav_order`, `weight`, `draft`, `hidden` and `unlisted` all change what a reader sees.
## No repository access
Crawl instead, and label the inventory as nav-only:
1. Fetch `sitemap.xml` for the full URL set, and the rendered navigation for the intended tree.
2. Diff them: URLs in the sitemap but not in the nav are orphan candidates.
3. Accept the limits - you cannot see drafts, hidden pages, front matter or last-modified dates, so drop staleness and orphan measures from the scorecard rather than guessing them.
If neither a repository nor a live site is reachable, ask the user to paste the navigation tree and work from titles alone; say in the report that classification came from titles, which is the weakest evidence available.
## Inventory script
`scripts/docs-inventory.py` walks the docs tree and emits one row per page with the facts the classification pass needs.
```bash
# Markdown docs with a MkDocs nav
python3 scripts/docs-inventory.py ./docs --nav mkdocs.yml > inventory.tsv
# Docusaurus, several nav sources, JSON for further processing
python3 scripts/docs-inventory.py ./docs --nav sidebars.ts --nav docusaurus.config.ts --format json
# Sphinx project, ignore stubs under 50 words
python3 scripts/docs-inventory.py ./doc --ext .rst,.md --nav doc/index.rst --min-words 50
```
Columns: `path`, `title`, `words`, `headings`, `max_heading_depth`, `code_blocks`, `numbered_steps`, `imperatives`, `option_table`, `questions`, `internal_links`, `external_links`, `in_nav`, `last_modified`. Orphan candidates are printed to standard error so they stay out of the TSV.
Reading the columns:
- `numbered_steps` + `imperatives` high, `option_table` 0 → action content: tutorial or how-to.
- `option_table` 1 with few steps → reference.
- Long, few code blocks, few steps → explanation, or an over-long page hiding several modes.
- `numbered_steps` high **and** `option_table` 1 → mixing candidate; open the page.
- `words` above ~2,500 with `max_heading_depth` ≥ 4 → a page that has absorbed several modes.
- `in_nav` `no` → orphan candidate; confirm against front matter (a `draft`/`unlisted` page is intentional).
The nav matcher is heuristic across generators: it extracts path-like tokens from any config format and matches by stem. Confirm orphan candidates before reporting them, and skip the `--nav` flag entirely for generators whose order lives in front matter (Hugo, Jekyll), where it produces noise. The columns are a shortcut, not a requirement - the hand-built fallback is in SKILL.md Step 2.
references/gap-and-signal-analysis.md›
# Finding what is missing
## Coverage matrix
Build rows from the product's real surfaces - the things a user adopts one at a time (each SDK or language, each major feature, each deployment target, each integration) - and columns from the four modes.
| Surface | Tutorial | How-to | Reference | Explanation |
| ------------ | ------------- | -------- | ------------------------ | -------------------- |
| Python SDK | quickstart.md | 4 guides | api/python.md | - |
| Webhooks | - | 1 guide | reference/events.md | concepts/delivery.md |
| Self-hosting | - | - | reference/helm-values.md | - |
Read it as a heat map:
- Empty **reference** on a surface users configure is the most damaging gap - it sends people to source code or support.
- Empty **how-to** on a surface with real-world variability produces repeat support tickets.
- Empty **tutorial** anywhere in the product means no supported entry point; one good tutorial per audience is usually enough, not one per feature.
- Empty **explanation** shows up later as mistrust: users cannot predict the system, so they do not build on it.
- A row that is empty except for reference describes an undocumented feature with an API dump.
Do not demand a full grid. A minor surface may legitimately need only reference plus one how-to. Justify each proposed page with a signal below, or leave the cell empty and say why.
## Demand signals
Structure cannot tell you what readers wanted and did not find. Gather what the user can actually reach - ask before assuming any of it exists, and mark any conclusion drawn without signals as an inference.
| Signal | Where it lives | What it proves |
| --------------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------- |
| Site-search queries with zero results | docs search analytics | A missing page, named in the user's own words |
| Site-search queries with results but no click | same | A page exists but its title/snippet does not match the need |
| Support ticket clusters | helpdesk tags, deflection reports | Repeat cost of a missing or unfindable page |
| Issues labelled question/support/docs | repository | Public, quotable evidence for prioritization |
| Repeated community questions | Discord/Slack/forum/public Q&A | Same question three times = missing page |
| High-exit, high-traffic pages | web analytics | Page answers the search but not the need |
| Sales and solutions-engineer FAQs | internal | Evaluator questions (limits, security, migration) that never reach public channels |
| Coding-agent failures against your docs | agent transcripts, integration attempts | Missing machine-readable reference or ambiguous naming |
Rank gaps by evidence volume × adoption impact, not by how uncomfortable the hole looks in the matrix.
A high-exit or high-bounce page is not always a failure: it can mean the reader found the answer immediately and left satisfied. One documentation team restructured its docs around clear navigation and FAQ-style entries, then deliberately stopped treating page views and time-on-page as success metrics, tracking bounce rate, self-service rate and case deflection as positive outcomes instead (Stephan Delbos, "Drop the Docs, Get Back to What's Important! How to Create Product Documentation that Encourages User Disengagement", Write the Docs Atlantic 2023, on Mews's documentation restructuring). Pair an exit-rate reading with a support-ticket trend or a satisfaction prompt before logging it as a gap.
## Audience weighting
The same product documented for different buyers needs a different mode mix. Ask who the docs serve before judging balance.
- **Self-serve individual developers** (bottom-up, credit-card or free adoption): weight tutorials and how-tos, keep time-to-first-success short, expect entry from search on an error or a task. Explanation earns its place only where a surprising mental model blocks usage.
- **Team and enterprise adoption** (B2B, an evaluator and a signer behind the user): add explanation early - architecture, security model, limits, cost model, migration path - because someone who will never run the quickstart has to approve the choice. Reference completeness carries procurement weight; missing limits and compliance detail become sales blockers.
- **Both audiences on one site**: keep one entry point per audience rather than one merged tour, and do not let evaluator content colonise the getting-started path.
references/scoring-rubrics.md›
# Scoring a docs set
## Layer 1 - CNCF TechDocs rubric (sourced)
The CNCF TechDocs team runs a published documentation assessment program for CNCF projects. It is the most concrete public instrument for scoring an existing docs set, and it is free to reuse on any project.
Score each top-level docs section, then the set as a whole, on the 2024 named scale:
| Score | Meaning |
| ----- | -------------------------- |
| 1 | Not present |
| 2 | Needs improvement |
| 3 | Meets standards |
| 4 | Meets or exceeds standards |
| 5 | Exemplary |
An older CNCF template names only the odd anchors (1 = not present or requires significant work, 3 = present but needs work, 5 = executed extremely well). Use the named 1-5 scale; it forces a decision at 2 and 4.
Rubric categories:
- **Project documentation** (end users): Information architecture, New user content, Content maintainability, Content creation processes, Inclusive language.
- **Contributor documentation**: Communication methods documented, Beginner-friendly issue backlog, "New contributor" getting-started content, Project governance documentation.
- **Website** (infrastructure): twelve criteria covering single-sourcing, branding, accessibility, mobile, HTTPS, production-only analytics and indexing, intra-site search, and documented account custodians.
A structure audit owns the Project documentation category in full and touches Website only through intra-site search. Score contributor documentation only when the user asks for it.
**Published calibration.** The 2024 CNCF analysis of TUF scored these ratings:
- Project documentation: Information architecture 2, New user content 1, Content maintainability 3, Content creation processes 1, Inclusive language 3.
- Contributor documentation: Communication methods 3, Beginner-friendly backlog 1, "New contributor" getting-started 1, Project governance 3.
Read that as the realistic baseline for a serious open-source project with no dedicated writer: mostly 1s and 2s on entry-point and process criteria, 3s where a maintainer culture already exists. A first audit returning straight 4s usually means the rubric was applied too generously, not that the docs are exemplary.
**Deliverable shape.** CNCF splits the output into three documents:
- An analysis (ratings plus comments).
- An implementation plan that breaks recommendations into "achievable work that can be completed in constrained blocks of time".
- An issues document contributors can pick from.
Mirror that split - the report, the queue, and the tickets are three different artefacts with three different readers.
Source: github.com/cncf/techdocs; contribute.cncf.io/techdocs/analyses/2024/TUF/analysis.
## Layer 2 - structural scorecard (this skill's baseline)
The targets below are this skill's own baseline, chosen to be achievable on a mid-sized docs set. State them as such in the report and agree them with the user before scoring - a 30-page project and a 900-page platform do not pass on the same numbers.
| Measure | How to compute | Baseline target | Source |
| --------------------- | ----------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------- |
| Mode purity | single-mode pages ÷ total pages | ≥ 90% | self-set |
| Surface coverage | surfaces carrying the modes their usage requires ÷ surfaces | 100% of top surfaces | self-set |
| Entry points | one tutorial or quickstart per primary audience | present | Diátaxis (a missing quadrant strands a class of visitor) |
| Orphans | pages absent from navigation | 0 | self-set |
| Dead nav entries | nav entries with no page | 0 | self-set |
| Broken internal links | link checker over the built site | 0 | self-set |
| Nav depth | deepest navigation level | ≤ 3 | self-set |
| Thin sections | nav sections holding a single page | 0 | self-set |
| Demand coverage | top 20 recurring questions with a findable answer | ≥ 90% | self-set |
| Staleness | pages untouched since the last major release | ≤ 10% | self-set |
| ROT rate | pages flagged Redundant, Outdated or Trivial ÷ total | report, no target | ROT is a standard content-audit heuristic; report the rate rather than grading it |
An audit that never gets re-scored becomes a document nobody trusts.
## ROT and inventory columns (sourced method)
The standard qualitative heuristic is **ROT** - Redundant, Outdated/Obsolete, Trivial. For many teams ROT _is_ the audit.
Kristina Halvorson's _Content Strategy for the Web_ chunks the qualitative pass into six groups:
- Usability.
- Knowledge level.
- Findability.
- Actionability.
- Audience.
- Accuracy.
Decay analysis adds a 90-day versus prior-90-day comparison from Search Console and analytics, and prioritises URLs that trip several decay signals _and_ carry an O or R flag.
Sources: NN/g "Content Inventory and Auditing 101"; Optimal Workshop; UXmatters; Click Laboratory.
## Why a fixed docs set drifts back (maturity read)
If the team has fixed its structure before and it decayed, the problem is organisational, not structural. JoAnn Hackos's Information Process Maturity Model, from _Managing Your Documentation Projects_ (1994), patterned on the software CMM, places a documentation organisation on five levels:
- Ad hoc.
- Rudimentary.
- Organized and repeatable.
- Managed and sustainable.
- Optimizing.
It assesses ten characteristics, including organizational structure, quality assurance, planning, information design, change management and collaboration.
A team at "ad hoc" or "rudimentary" has no repeatable process, so any structural fix decays. Say so in the report and put the governance layer ahead of further page surgery.
The ISO/IEC/IEEE 265xx family covers the same ground as formal standards. 26514:2022 (design and development of information for users) is the current revised base standard, and its three pillars map onto this audit's inventory, classification and validation steps:
- Audience analysis.
- Derivation of information concepts.
- Usability validation.
Sources: TCBOK; IEEE/ACM 10.1109/IPCC.2017.8013946; iso.org/standard/43073.html.
references/validation-and-governance.md›
# Validating a proposed structure, and keeping it
## Who owns a structure audit
The deliverable set for a structure engagement belongs to an information architect and a content strategist:
- Content inventory spreadsheet.
- IA/sitemap diagram.
- Taxonomy.
- Content model spec.
- Metadata schema.
- Migration plan.
- Governance doc.
NN/g's framing is worth repeating to anyone who thinks this is a one-afternoon job: "The IA is much more than just a sitemap. It's a very involved process of constantly making decisions about how your content is organized and maintained."
Three failure modes follow predictably when a generalist runs the audit alone:
- Treating it as a one-off friction log instead of a repeatable inventory-plus-rubric pass.
- Optimising the hero getting-started path while reference and explanation stay unstructured.
- Skipping user validation entirely.
When no writer exists - the normal case in open source - ownership of the structure sits with maintainers through CODEOWNERS and PR review, on top of the external-program routing in SKILL.md.
Sources: NN/g "Information Architecture vs. Sitemaps"; Bynder; Tahzoo; State of Developer Relations Report 2023.
## Card sorting and tree testing
Classification and demand signals say what is wrong today. Only user testing says whether the _proposed_ structure is better.
- **Card sorting** (open, closed or hybrid) surfaces users' mental models and generates candidate categories.
- **Tree testing** validates a proposed hierarchy by measuring task success and first-click accuracy against a text-only tree, isolating structure from visual design.
- **Sequence**: card sort to design, tree test to validate. OptimalSort and Treejack are the industry-standard pair; UXtweak, Maze, UserZoom and Miro cover the same ground.
**Sample sizes that real projects used.** A published GovWebworks engagement ran an open card sort with 69 participants sorting 30 labelled cards, then "asked 222 remote participants to complete four tasks to evaluate the performance of the proposed information architecture." Treat ~60-70 for the sort and 4-6 tasks for the tree test as the working target; the 222-participant tree test is an upper bound, not a requirement.
**A docs-team validation without commercial tooling.** A newly formed technical-writing team inheriting an engineer-written docs set combined three checks instead of one: a content audit, a structural comparison against competitor documentation, and an in-house usability study of real users (Jeffrey Boruszak and Adam Trujillo, "Bootstrap IA Development with In-house Usability Testing", Write the Docs Atlantic 2023). The usability study exposed where actual navigation behaviour diverged from the team's assumptions; the findings split into quick wins shipped immediately and a longer IA roadmap, both delivered ahead of a major launch with no added headcount.
**Interpreting results** (practitioner heuristics, not an authoritative standard):
| Reading | Diagnosis | Action |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Task success ~45% | "A clear sign that the current categorization is confusing" | Restructure before shipping |
| Task success < ~60% | Structure fails on that task | Restructure that branch |
| Direct-path rate < ~40% | Users get there by wandering | Relabel, then re-test |
| 90% success with 30% direct path | "Users find the content eventually but get lost along the way - the category labels are ambiguous" | Fix labels, keep the tree |
| > 80% success and > 60% direct path across core tasks | Structure is not the bottleneck | **Cancel the restructure**; spend the budget on gap-filling and freshness |
That last row is the most valuable one in this file. A restructure that a tree test says is unnecessary costs a quarter of writing time and breaks every inbound link for nothing.
**When user testing is not available**, say so in the report and downgrade every structural recommendation from "validated" to "proposed". Analytics substitute partially:
- Top 404s (the CNCF assessment template explicitly asks reviewers to "include a list of the top 404s, as reported through analytics or a search console").
- Zero-result site searches.
- High-exit landing pages.
Sources: NN/g "Card Sorting vs. Tree Testing"; Optimal Workshop; CorsoUX practical guide; GovWebworks UX Playbook Part 2 (2018-10-23); CNCF Falco assessment template; Jeffrey Boruszak and Adam Trujillo, "Bootstrap IA Development with In-house Usability Testing", Write the Docs Atlantic 2023.
## Governance: keeping the structure after the audit
An audit's fixes decay without an enforcement layer. Recommend these as part of the queue, not as a follow-up project.
**Declare the content type in front matter and validate it in CI.** Microsoft Learn requires `title`, `description`, `author`, `ms.author`, `ms.date` and `ms.topic`, and omitting a required attribute "will likely get a validation error during build". The docs-as-code equivalent is a JSON Schema for front matter enforced in CI. A page whose declared type and actual content disagree is then a build failure, not an audit finding two years later.
**Ship page templates so contributors fill blanks instead of inventing structure.** The Good Docs Project templates (explanation, how-to, README, reference, release notes, troubleshooting, tutorial, quickstart, API overview) follow the Diátaxis types directly, so they combine with a Diátaxis audit rather than competing with it. Microsoft Learn and Kubernetes publish equivalent template sets.
**Lint prose and structure in CI.** Vale is the de facto docs-as-code prose linter: a Go CLI that runs locally, in editors and in CI, and ships the Microsoft and Google style guides as packages.
It is fast enough not to be an excuse - vale.sh reports that "GitLab runs 82 rules across all 2,827 pages of its documentation in under twenty seconds."
Pair it with markdownlint, and with the generator's own strict mode (MkDocs strict, Sphinx nitpick, Docusaurus broken-link check).
**Check links on a schedule, not at review time.** lychee is the current standard, an async Rust checker for Markdown/HTML/rST:
- Validates anchor fragments (`--include-fragments`).
- Caches results.
- Ships a GitHub Action.
- Is commonly run on a daily cron that opens an issue on failure.
htmltest is the Hugo-native alternative.
**Assign owners.** CODEOWNERS auto-requests review from the maintainers of a subtree; CNCF recommends it for large codebases and a single-reviewer minimum for small teams. Add a PR template that makes the author declare the content type and confirm it matches the template.
**Keep URLs stable.** Maintain a redirect for every page move and prefer relative internal links. A structure audit that breaks inbound links trades one findability problem for another.
**Re-audit quarterly.** Run this cadence quarterly, using 90-day versus prior-90-day analytics windows, so the audit does not depend on one person remembering to export data:
1. Inventory.
2. Score.
3. Prioritise.
4. Refresh.
5. Measure.
Sources: learn.microsoft.com/contribute/content/metadata; thegooddocsproject.dev/template; vale.sh; github.com/lycheeverse/lychee; CNCF "Security Hygiene Guide for Project Maintainers"; Click Laboratory.
scripts/docs-inventory.py›
#!/usr/bin/env python3
"""Inventory a documentation source tree for a structural audit.
Walks a docs directory, emits one TSV row per page with the facts a mode
classification needs, and optionally compares the file tree against a
navigation config to surface orphans and dead nav entries.
Usage:
docs-inventory.py <docs-dir> [--nav <config-file> ...] [--format tsv|json]
[--ext .md,.mdx,.rst] [--min-words N]
Columns: path, title, words, headings, max_heading_depth, code_blocks,
numbered_steps, imperatives, option_table, questions, internal_links,
external_links, in_nav, last_modified.
The nav comparison is deliberately heuristic: it pulls path-like strings out
of any config format (yaml, js, ts, json, md) and matches them against the
inventory by stem, so it works for MkDocs, Docusaurus, VitePress, Mintlify,
Starlight, Nextra, GitBook and Sphinx without a parser per generator. Treat
its orphan list as candidates to confirm, not as verdicts.
"""
import argparse
import json
import os
import re
import subprocess
import sys
FENCE = re.compile(r"^\s*(```|~~~|\.\. code-block::)")
ATX = re.compile(r"^(#{1,6})\s+(.+?)\s*#*$")
RST_TITLE = re.compile(r"^[=\-~^\"']{3,}\s*$")
NUMBERED = re.compile(r"^\s*(\d+[.)]\s+|[-*]\s+\d+[.)]\s+)")
IMPERATIVE = re.compile(
r"^\s*(?:\d+[.)]\s*)?(Run|Install|Open|Click|Create|Add|Set|Copy|Paste|Navigate|"
r"Deploy|Configure|Replace|Select|Enter|Start|Stop|Download|Import|Export|Update)\b"
)
TABLE_ROW = re.compile(r"^\s*\|.*\|\s*$")
OPTION_WORDS = re.compile(
r"\b(parameter|argument|option|flag|field|property|returns?|type|default|required)\b", re.I
)
LINK = re.compile(r"\]\(([^)]+)\)")
NAV_PATH = re.compile(r"[\"'`]?([\w./-]+(?:/[\w.-]+)*)[\"'`]?")
def read(path):
with open(path, "r", encoding="utf-8", errors="replace") as handle:
return handle.read()
def title_of(lines, path):
for index, line in enumerate(lines):
match = ATX.match(line)
if match:
return match.group(2).strip()
# reStructuredText: a line underlined by punctuation is a title.
if index + 1 < len(lines) and line.strip() and RST_TITLE.match(lines[index + 1]):
return line.strip()
return os.path.splitext(os.path.basename(path))[0]
def last_modified(path, root):
try:
out = subprocess.run(
["git", "log", "-1", "--format=%as", "--", path],
cwd=root, capture_output=True, text=True, timeout=10,
)
return out.stdout.strip() or "unknown"
except (OSError, subprocess.SubprocessError):
return "unknown"
def analyse(path, root):
text = read(path)
lines = text.splitlines()
stats = {
"path": os.path.relpath(path, root),
"title": title_of(lines, path),
"words": 0, "headings": 0, "max_heading_depth": 0, "code_blocks": 0,
"numbered_steps": 0, "imperatives": 0, "option_table": 0, "questions": 0,
"internal_links": 0, "external_links": 0,
}
in_code = False
table_rows = 0
for line in lines:
if FENCE.match(line):
in_code = not in_code
if in_code:
stats["code_blocks"] += 1
continue
if in_code:
continue
stats["words"] += len(line.split())
heading = ATX.match(line)
if heading:
depth = len(heading.group(1))
stats["headings"] += 1
stats["max_heading_depth"] = max(stats["max_heading_depth"], depth)
if heading.group(2).rstrip().endswith("?"):
stats["questions"] += 1
if NUMBERED.match(line):
stats["numbered_steps"] += 1
if IMPERATIVE.match(line):
stats["imperatives"] += 1
if TABLE_ROW.match(line):
table_rows += 1
if OPTION_WORDS.search(line):
stats["option_table"] = 1
for target in LINK.findall(line):
if target.startswith(("http://", "https://")):
stats["external_links"] += 1
elif not target.startswith("#"):
stats["internal_links"] += 1
# A long table without option vocabulary is still reference-shaped material.
if table_rows >= 6:
stats["option_table"] = 1
stats["last_modified"] = last_modified(path, root)
return stats
def nav_references(nav_files):
"""Return (page refs, section prefixes) found in navigation configs.
A token written as `user-guide/` covers every page below it (MkDocs and
Sphinx globs, Docusaurus autogenerated sidebars), so it is kept apart from
exact page references and matched as a prefix.
"""
refs, prefixes = set(), set()
for nav in nav_files:
for token in NAV_PATH.findall(read(nav)):
if not ("/" in token or token.endswith((".md", ".mdx", ".rst"))):
continue
cleaned = os.path.splitext(token.strip("./"))[0].lower()
if not cleaned:
continue
if token.rstrip("\"'`").endswith("/") or token.endswith("*"):
prefixes.add(cleaned.rstrip("*/"))
else:
refs.add(cleaned)
return refs, prefixes
def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("docs_dir")
parser.add_argument("--nav", action="append", default=[], help="navigation config file (repeatable)")
parser.add_argument("--ext", default=".md,.mdx,.rst")
parser.add_argument("--min-words", type=int, default=0, help="skip pages shorter than N words")
parser.add_argument("--format", choices=["tsv", "json"], default="tsv")
args = parser.parse_args()
root = os.path.abspath(args.docs_dir)
if not os.path.isdir(root):
sys.exit(f"not a directory: {root}")
extensions = tuple(e if e.startswith(".") else "." + e for e in args.ext.split(","))
skip = {".git", "node_modules", "build", "dist", ".venv", "__pycache__", "_build", "site"}
pages = []
for base, dirs, files in os.walk(root):
dirs[:] = [d for d in dirs if d not in skip and not d.startswith(".")]
for name in sorted(files):
if name.endswith(extensions):
pages.append(analyse(os.path.join(base, name), root))
pages = [p for p in pages if p["words"] >= args.min_words]
refs, prefixes = nav_references(args.nav) if args.nav else (set(), set())
for page in pages:
stem = os.path.splitext(page["path"])[0].lower()
listed = any(
stem == r or stem.endswith("/" + r) or r.endswith("/" + stem) or
(os.path.basename(stem) == "index" and os.path.dirname(stem) == r)
for r in refs
) or any(stem.startswith(p + "/") for p in prefixes)
page["in_nav"] = "" if not (refs or prefixes) else ("yes" if listed else "no")
if args.format == "json":
print(json.dumps(pages, indent=2))
return
columns = ["path", "title", "words", "headings", "max_heading_depth", "code_blocks",
"numbered_steps", "imperatives", "option_table", "questions",
"internal_links", "external_links", "in_nav", "last_modified"]
print("\t".join(columns))
for page in pages:
print("\t".join(str(page.get(c, "")) for c in columns))
orphans = [p["path"] for p in pages if p.get("in_nav") == "no"]
if refs or prefixes:
print(f"\n# pages: {len(pages)}\t# nav entries: {len(refs) + len(prefixes)}\t# orphan candidates: {len(orphans)}",
file=sys.stderr)
for path in orphans:
print(f"orphan-candidate\t{path}", file=sys.stderr)
if __name__ == "__main__":
main()
SKILL.md›
---
name: developer-docs-structure-audit
description: Audits an existing developer documentation set's structure - a page-by-page inventory classified against the Diátaxis modes (tutorial, how-to, reference, explanation), mixed-mode and misplaced pages, coverage gaps per product surface, navigation drift against the file tree, a CNCF TechDocs rubric score, and a prioritized remediation queue. Use whenever the user mentions a docs structure or content audit, docs information architecture, Diátaxis, "our documentation is a mess", a docs gap analysis, what docs are missing, where a page should live, or reorganizing a documentation site - even if they only say "our docs are hard to navigate". Not for writing pages. Do NOT use for docs search ranking - use samber/developer-relations-skills@docs-seo.
license: MIT
metadata:
author: Samuel Berthe
version: "1.0.1"
---
# Docs Structure Audit
You are an information architect for developer documentation. Someone has a docs set that already exists and a suspicion that readers cannot find what they need.
Say, with evidence, page by page:
- Which pages sit in the wrong place.
- Which pages try to do two jobs at once.
- Which pages were never written.
Hand back a queue of small moves the team can actually ship.
**In scope:** placement, coverage, findability.
**Out of scope:** writing the pages, verifying that documented behaviour matches the code, editing prose. When the request is really "write this page", route it to the sibling skills listed under References instead of absorbing the work.
## Who should run this
This work belongs to an information architect or content strategist. The field's own data shows what happens when a generalist runs it instead: the _State of Developer Relations Report 2023_ found 44% of respondents "Never" audit their developer experience or review developer journey maps, and only 1% review monthly - down from 12.4% the year before.
Two things follow:
- Run the full inventory-and-rubric pass below rather than a walkthrough of whatever pages you happen to open. [./references/validation-and-governance.md](./references/validation-and-governance.md) names the three failure modes a solo generalist pass falls into.
- When the project has no writer at all (the normal case in open source), tell the user that the CNCF TechDocs assistance program and Google Season of Docs both provide an external analysis, an implementation plan and an issues backlog for free, and that either beats a solo pass. Run this audit as the interim measure while they apply.
## Interview
Ask one question at a time, multiple-choice where you can, and skip anything already answered. Questions 1-4 gate the audit; do not classify a single page before they are answered.
**Memory: Store a few info about the current task or project context. When memory lives in a file, use `devrel-context.md`; if a different memory system is in use, rely on that instead. Separate task info in different sections. Remove finished tasks. Add a date to a task; no date for general project context. Some interview responses may differ between 2 tasks.**
1. Where do the docs live: a repository you can read, a public site only, or neither (you will paste the tree)?
2. Which generator - MkDocs, Docusaurus, Sphinx, VitePress, Mintlify, Starlight, Hugo, GitBook, something else, or hand-rolled?
3. Who reads them: individual developers adopting self-serve, engineering teams whose company signs a contract, or both? Which ecosystems or languages?
4. What triggered the audit - a support pattern, a launch, a migration, a complaint, or a routine review?
5. What are the product's real surfaces (SDKs, features, deployment targets, integrations) that a user adopts one at a time?
6. Which demand signals can you reach: docs search analytics, support tickets, repository issues, community channels, page analytics, sales FAQs?
7. Does the site already declare a content-type taxonomy - Diátaxis, DITA concept/task/reference, Microsoft `ms.topic`, Good Docs templates, house-defined, or none?
8. Is any part of the docs out of scope - auto-generated API reference, a legacy version, a partner portal?
9. Can you run user testing (a card sort or a tree test) on a proposed structure, or is this a desk audit?
10. Who will do the remediation, how many writing hours per week do they actually have, and is there a docs CI pipeline you can add checks to?
11. Has a structure been imposed before (a Diátaxis attempt, a nav rewrite), and what happened to it?
12. Any constraint on moving pages: URL stability, redirects, translations, a docs platform that pins the hierarchy?
13. What date does the remediation have to show a result by?
14. Do you want a one-off cleanup before that date, or a structure the team keeps governed for years?
Questions 10, 12, 13 and 14 re-rank the queue in Step 8, so ask them before you classify:
- A near date promotes splits and moves, the actions that ship in a day.
- A governance mandate promotes writing the missing pages and the drift controls.
- A refusal to ship redirects deletes moves and renames from the queue entirely.
- An engineer-only remediation team pushes every writing-heavy action down the order.
If the user cannot answer 3, infer the audience from the top entry pages in analytics and say in the report that the audience is inferred - mode balance judged against the wrong audience produces confident, wrong recommendations.
## Step 1 - Fix the scope and the evidence you have
Decide what you can see before promising what you can measure:
- Repository access gives you the file tree, front matter, nav config and git history.
- A live site gives you the rendered nav and the sitemap.
- Neither leaves you with titles alone.
Drop from the scorecard any measure your evidence cannot support, and say so in the report. See [./references/docs-platform-nav-sources.md](./references/docs-platform-nav-sources.md) for where navigation lives per generator and the crawl fallback.
## Step 2 - Build the inventory
Keep the two halves of the pass distinct:
- **Inventory**: the quantitative list of every page with its characteristics.
- **Audit**: the qualitative judgement of that list.
Build the inventory first, completely, before judging anything.
Run the inventory script over the docs tree; it collects the per-page facts that classification runs on, plus orphan candidates when you pass the navigation config.
```bash
python3 scripts/docs-inventory.py ./docs --nav mkdocs.yml > inventory.tsv
```
Per-generator flags (`--nav`, `--ext`, `--min-words`, `--format json`), the emitted columns and how to read them are in the platform reference.
Add the columns the script cannot know - owner, page views, top search-entry queries, top 404s - from whatever analytics the user has, and flag each page **R**edundant, **O**utdated or **T**rivial. ROT is the standard content-audit heuristic and it does most of the triage work for free: an outdated page in a well-placed section still fails its reader.
If you cannot execute scripts or read the tree directly, build the same inventory by hand from the navigation and the pages you can open, and note in the report that it is partial.
Do not classify from the numbers alone. Use them to triage - these cutoffs are this skill's working defaults, not published figures. Open:
- Every page on the adoption path.
- Every page above ~2,500 words.
- Every page combining steps with option tables.
- A sample of the rest.
On a large docs set, cover the top 20 pages by traffic in full before sampling.
## Step 3 - Classify every page
Apply the compass to each page's dominant content: does it inform **action** or **cognition**, and does it serve the reader's **acquisition** of skill (study) or **application** of skill (work)? Those two answers give the mode.
If the site already declares a different taxonomy (question 7), audit against that one instead and say so up front. Practitioners converge on consistency mattering more than which framework supplies it, so a DITA site applying concept/task/reference cleanly is healthy, and telling it to convert is expensive advice. Recommend a switch only when the declared taxonomy is applied inconsistently or leaves a whole reader need uncovered.
Record for each page:
- Assigned mode.
- Confidence.
- Whether a second mode is present.
- Where the page currently sits in the navigation.
Two disagreement types follow:
- A page whose assigned mode disagrees with its section is a placement finding.
- A page holding two modes is a mixing finding.
Read [./references/diataxis-classification.md](./references/diataxis-classification.md) for acceptance criteria per mode, the mixing symptom table, worked examples, the hard cases (release notes, FAQ, troubleshooting, generated API docs), and how to audit a DITA, EPPO, Microsoft, or Good Docs site.
Flag mixing only when the second mode occupies roughly a fifth of the page - this skill's working line, not a published threshold - or contains something the reader must act on. Flagging every stray sentence produces a report nobody triages.
## Step 4 - Find what is missing
Build the coverage matrix: product surfaces as rows, the four modes as columns, existing pages in the cells. Empty cells are candidate gaps, not confirmed ones.
Confirm each candidate against a demand signal from the signal table in [./references/gap-and-signal-analysis.md](./references/gap-and-signal-analysis.md), which also has the matrix and the audience weighting (self-serve versus enterprise evaluation). A gap with evidence goes in the queue with the evidence attached; a gap without evidence gets listed as a question for the team, not as work.
## Step 5 - Check that navigation tells the truth
Run the mechanical checks first - the inventory script, the nav config and a link checker answer these without judgement:
- Orphans (pages absent from the navigation).
- Nav entries pointing at nothing.
- Broken internal links and anchors.
- Single-page sections.
- Depth beyond three levels.
Confirm orphans against front matter before reporting; `draft`, `hidden` and `unlisted` pages are intentional.
Then open pages and judge these by hand:
- Titles that promise a different mode than the page delivers ("Getting started" that is a reference dump, "Concepts" holding procedures).
- Declared content type in front matter disagreeing with the page's actual mode.
- One concept named three ways across sections ("project", "workspace", "org") - readers searching one name miss the pages that use another, so a split vocabulary breaks site search even when placement is right.
- Duplicate content living in two places and already diverging.
- Sections that will not survive growth: a flat list already past ~30 entries (this skill's working heuristic), or a category the product roadmap will double.
## Step 6 - Score
Score twice: the rubric rating travels outside the docs team; the scorecard drives the remediation queue.
Rate each top-level section on the CNCF TechDocs rubric's project-documentation criteria, on its published 1-to-5 scale - the most concrete public instrument for scoring a docs set, and a rating a third party would recognise. Then compute the structural scorecard from the inventory; the eleven measures, how to compute each, and each threshold's source are in [./references/scoring-rubrics.md](./references/scoring-rubrics.md), along with the rubric's published calibration ratings and the maturity read that explains a docs set that keeps drifting back.
Label every threshold with where it came from. The CNCF scale is published; the scorecard's pass marks are this skill's own baseline, so agree them with the user before scoring rather than importing them silently. Treat the audit as unfinished while any must-fix measure fails - after each remediation batch, re-run the inventory, re-score, and report the delta.
## Step 7 - Validate before recommending a restructure
Classification says what is wrong today; only user testing says whether your proposed structure is better. When question 9 says testing is possible, card sort to design the categories and tree test to validate them, then read the result before writing the queue.
One reading changes the plan outright: above roughly 80% task success and 60% direct-path rate across core tasks, cancel the restructure and spend the budget on gap-filling and freshness instead. These are practitioner heuristics from one guide plus one case study, not a standard, so treat a borderline number as a prompt to talk to the team, not a verdict.
When testing is not possible, downgrade every structural recommendation from "validated" to "proposed" in the report, and lean harder on top 404s, zero-result searches and high-exit landing pages as substitutes.
[./references/validation-and-governance.md](./references/validation-and-governance.md) has the method, real sample sizes, the full interpretation table and its sourcing.
## Step 8 - Turn findings into a queue
Order the work so every item ships alone and improves the docs by itself. Diátaxis's own remediation loop is deliberately small:
1. Choose something.
2. Assess it.
3. Decide the single next action that produces an immediate improvement.
4. Do it.
5. Publish.
6. Repeat.
It rules out two moves you should rule out too:
- **Never propose empty scaffolding.** The framework's wording is blunt: "It certainly does not mean that you should create empty structures for tutorials/howto guides/reference/explanation with nothing in them. Don't do that. It's horrible." Four new top-level sections holding three pages advertise the gaps and force readers to learn a vocabulary before they can navigate.
- **Never propose a teardown.** "Rewrite the docs site" is not a recommendation, it is an abdication. Keep the documentation useful at every step of the remediation.
Within that loop, order the queue by reader need fixed per hour of writing and review - not by how many findings an action closes, and not by what is cheapest. The Diátaxis loop prescribes only one small action at a time; the ranking below is this skill's own.
| Action | Effort | Reader need it fixes |
| -------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------- |
| Split a mixed page | a day - both halves rewritten, two URLs, one redirect; no SME arbitration | the reader stops landing on a page doing two jobs |
| Merge duplicates | a day or more - someone with authority must say which text is true | the reader stops getting two contradictory answers |
| Move a page | an hour - a path change plus its redirect | the reader finds the page where the section promised it |
| Write a missing page | a week, then a refresh every release - permanent surface | the reader gets an answer where they got nothing |
| Rename a section | an hour of editing, but every child URL and deep link moves with it | the reader reads a label matching what is inside |
- efficiency: split > merge > move > write a missing page > rename
- value: merge > write a missing page > split > move > rename
- effort: write a missing page > merge > split > rename > move
Split leads on efficiency despite merging being worth more, because a merge blocks on someone else deciding which text is correct and a split does not. Default to shipping every split first, and move up to merging as soon as a duplicate pair is giving contradictory answers on the adoption path.
This order starves the missing page: highest value on a gap with a confirmed demand signal, a week of writing plus upkeep every release, so it loses every round and the section ratings never move while only cheap edits ship. Promote it anyway when the same question recurs in support week after week, or when the gap sits on the adoption path.
Delete rather than demote what the constraints rule out:
- A team that cannot ship redirects (question 12) has no move and no rename in its queue, since each one becomes a broken link.
- A tree test that already passes (Step 7) removes both as well.
Say which you deleted, and spend the budget on splits and gaps.
The ranking is a default, not a law, and it shifts with who executes it. Re-rank against what you already know:
- An existing page-template library makes writing the missing page far cheaper.
- An engineer-only team makes any writing-heavy action expensive.
- A platform that pins the hierarchy makes moves cost more than the table says.
When a page must move and URLs are load-bearing, name the redirect as part of the action.
## Step 9 - Deliver, then close the drift loop
Produce the report in the shape given by [./references/audit-report-template.md](./references/audit-report-template.md) - verdict, CNCF section ratings, scorecard, coverage matrix, findings by severity, remediation queue, drift controls, what the audit did not cover, and which inputs were available - using that file's finding format and severity tiers verbatim.
When the team will act on it, split the deliverable the way CNCF does - report, implementation plan, tickets - using the wording in the scoring reference. Present it section by section and get the user's agreement on each before moving on; a queue built on a wrong surface list wastes a whole sprint of writing time.
Close with the drift controls from the validation-and-governance reference, because a structure fixed once and left ungoverned decays:
- CI-validated content types.
- Page templates.
- Prose and link checking.
- CODEOWNERS per subtree.
- A redirect for every moved URL.
- A re-audit each quarter - this skill's default cadence, not a published standard.
If your environment has persistent memory, store the audit's durable decisions:
- The surface list.
- The audience weighting.
- The agreed thresholds.
- The mode assigned to each contested page.
- The queue's state.
A re-score six months later is worthless if the definitions moved in between.
## Failure modes
| Failure | What it looks like | Fix |
| --------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Framework worship | Findings phrased as "violates Diátaxis" | Phrase every finding as a reader failing to get something |
| Cheapest-first queue | Renames and moves at the top because they take an hour | Order by reader need fixed per hour, and say so in the report |
| Classification bikeshedding | Ten minutes on whether a page is reference or explanation | Apply the "while working / away from work" test, mark low confidence, move on |
| Over-flagging | 200 findings on a 200-page site | Report only the pages where a reader's need actually fails |
| Scope creep into accuracy | Findings about wrong code samples | Note them separately as out of scope with an owner |
| Audience blindness | Enterprise evaluator content judged as tutorial bloat | Settle the audience in the Interview, weight the target mix accordingly |
| Silent inference | Classification from titles presented as fact | Label evidence strength per finding |
| Audit with no governance | Report delivered, no CI check, same mess in a year | Ship the drift controls with the queue, not after it |
## References
- samber/developer-relations-skills@docs-seo for search-engine findability (mentioned in description as the alternative for ranking)
- samber/developer-relations-skills@developer-quickstart-guide for writing quick-start pages
- samber/developer-relations-skills@developer-tutorial for writing tutorial pages
- samber/developer-relations-skills@developer-troubleshooting-docs for writing troubleshooting pages
- samber/developer-relations-skills@docs-code-sample-standards for writing code samples this audit may reference
- samber/developer-relations-skills@developer-education-strategy for structured courses and certification, beyond what docs alone teach
- samber/developer-platform-skills@api-reference-quality when the audit narrows to whether the API reference is complete