{"id":"7810b245-8691-4b0f-91d2-e704cd551153","shortId":"mgKrnW","kind":"skill","title":"review-documentation","tagline":"Review documentation quality and sync with implementation across Go doc comments, proto comments, OpenAPI specs, markdown files, and example tests. Use when the user asks for a documentation review, doc audit, or wants to check that docs are in sync with code.","description":"# Documentation Review\n\nStructured documentation review producing actionable, prioritized findings with code-level references. Checks that documentation exists, is accurate, and stays in sync with the implementation.\n\n## Workflow\n\n### 1. Scope and explore\n\n- Confirm scope with the user: full codebase, specific packages/directories, changed files only (PR or branch diff), or specific concern.\n- **Resolve scope to a file/package list.** Based on what the user requested:\n  - **Changed files (PR or branch):** Run `git diff --name-only --diff-filter=d <base>...HEAD` to get changed files (default `<base>` is `main`). If the user references a PR number, use `gh pr diff <number> --name-only` instead. Filter to relevant file types (`.go`, `.proto`, `.md`, OpenAPI specs). Derive affected Go packages from the file paths (unique parent directories containing `.go` files).\n  - **Explicit paths/packages:** The user may specify directories (e.g. `internal/auth/`), Go package patterns (e.g. `./internal/auth/...`), or individual files. When given a directory or package pattern, include all files under it. Derive Go package paths for `go doc` invocations.\n  - **Full codebase:** No filtering; explore everything (default).\n- **Pass the resolved scope** (file list and derived package paths) to all exploration and investigation subagents so they only read and analyze scoped files.\n- Detect which documentation surfaces exist within the resolved scope:\n  - `.go` files → `go doc` analysis, `doc.go` files, `Example*` tests\n  - `.proto` files → service/method/message/field comments\n  - `openapi.yml` / `openapi.yaml` / `swagger.*` → API descriptions\n  - `*.md` files → README, guides, changelogs\n\n### 2. Launch investigation subagents in parallel\n\nLaunch up to 3 investigation subagents concurrently using the Task tool (`model: sonnet` per `subagent-model-routing` — documentation analysis requires cross-referencing signatures and prose). Each receives the list of in-scope files as context. Only launch subagents whose preconditions are met.\n\n> **Future fan-out note:** If per-symbol doc-comment presence checking is ever split into a dedicated fan-out subagent (e.g. one per package), use `model: haiku` per `subagent-model-routing` — presence checks are mechanical.\n\nEvery investigation subagent must check each finding against existing documentation: TODO comments, README notes, FIXME/HACK/XXX comments, and issue tracker references. Report tracked findings but mark them accordingly.\n\n**Subagent A: Go documentation** (`subagent_type=\"generalPurpose\"`, requires `.go` files)\n\nPrompt the subagent to:\n- Enumerate packages: run `go list ./...` for full-codebase scope, or `go list <package_paths>` for the resolved package paths when scope is narrowed.\n- For each package (sample if >20), run `go doc -all <pkg>` and inspect the output for:\n  - Missing package-level comment (no `doc.go` or empty package doc).\n  - Exported symbols (types, funcs, consts, vars) with missing or trivial (single-word, restating the name) doc comments.\n  - Doc comments that don't start with the symbol name or don't end with a period.\n  - Doc comment content that contradicts the actual function signature or behavior (parameter names, return types, error conditions).\n- Check for `Example*` test functions in `*_test.go` files. Flag key exported APIs that lack examples.\n- If `go doc` fails (e.g. build errors), fall back to reading `doc.go` and source files directly.\n- Include a **Tool Availability** section noting whether `go doc` ran successfully.\n- Return findings with `DOC-` prefixed IDs.\n\n**Subagent B: Proto and OpenAPI documentation** (`subagent_type=\"generalPurpose\"`, requires `.proto` files)\n\nPrompt the subagent to:\n- Read all in-scope `.proto` files and check for:\n  - Missing service-level comments.\n  - Missing RPC method comments.\n  - Missing or sparse message and field comments, especially fields with unclear names.\n- Glob for `openapi.yml`, `openapi.yaml`, `swagger.yml`, `swagger.yaml`, or `swagger.json` files.\n- If an OpenAPI spec exists, cross-reference against proto comments:\n  - Proto comments should appear as `description` fields in the OpenAPI spec.\n  - Flag drift: OpenAPI description empty despite proto comment existing, or content diverging.\n  - Flag missing `description` on endpoints, request/response schemas, and parameters.\n- Return findings with `DOC-` prefixed IDs.\n\n**Subagent C: Markdown and general docs** (`subagent_type=\"generalPurpose\"`)\n\nPrompt the subagent to:\n- Glob for `*.md` files across the repo.\n- Check README.md exists at the repo root. Flag if missing.\n- Scan markdown files for:\n  - Links to files that no longer exist (spot-check relative links against the file tree).\n  - References to CLI flags, env vars, or config keys; spot-check a sample against actual code.\n  - Code examples; spot-check function/type names against actual exports.\n- Flag large documentation gaps: no README, no CONTRIBUTING guide (for OSS projects), no architectural overview for multi-service repos.\n- Return findings with `DOC-` prefixed IDs.\n\n### 3. Summarize\n\nAfter all subagents complete, deduplicate overlapping findings, produce a consolidated table ordered by severity, and recommend fix order.\n\n### 4. Present results\n\nResolve the review output directory:\n\n```sh\nREVIEW_DATE=$(date +%Y-%m-%d)\nREVIEW_DIR=\"reviews/${REVIEW_DATE}\"\nif [ -d \"$REVIEW_DIR\" ]; then REVIEW_DIR=\"reviews/${REVIEW_DATE}-$(date +%H%M)\"; fi\nmkdir -p \"$REVIEW_DIR\"\n```\n\nCapture run metadata (see [Run metadata header](#run-metadata-header) below) and prepend the rendered block to `${REVIEW_DIR}/DOCUMENTATION-REVIEW.md`.\n\nWrite the output to `${REVIEW_DIR}/DOCUMENTATION-REVIEW.md`, structured as:\n1. Run metadata header\n2. Tool availability summary\n3. Consolidated findings table (with tracking status inline)\n4. Recommended fix order\n\nPresent the report to the user.\n\n---\n\n## Run metadata header\n\nCapture once near `REVIEW_DIR` resolution and prepend the rendered block to the output document:\n\n```sh\nRUN_DATETIME=$(date -u +\"%Y-%m-%d %H:%M UTC\")\nGIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)\nGIT_COMMIT=$(git rev-parse --short HEAD)\nGIT_COMMIT_FULL=$(git rev-parse HEAD)\nGIT_SUBJECT=$(git log -1 --pretty=%s)\n# When scope is diff-based, also: BASE_REF=<base>; BASE_COMMIT=$(git rev-parse --short \"$BASE_REF\")\n```\n\nHeader template (placed at the top of the output `.md`, before the H1 title):\n\n```markdown\n> **Run:** {RUN_DATETIME}\n> **Branch:** {GIT_BRANCH} @ {GIT_COMMIT} (`{GIT_COMMIT_FULL}`)\n> **Subject:** {GIT_SUBJECT}\n> **Base:** {BASE_REF} @ {BASE_COMMIT}   <!-- omit when scope is not diff-based -->\n> **Scope:** {scope description}\n```\n\n---\n\n## Finding link wrapping (PR mode)\n\nWhen the review is scoped to a GitHub PR (`pr_url` is provided by the caller, or, when run standalone, `gh pr view --json url -q .url 2>/dev/null` returns one), wrap every `path:line` reference inside the finding tables below as a Markdown link:\n\n```sh\n~/.claude/scripts/pr-deeplink.sh \"$pr_url\" <path> <line>\n# pr_url set   → [path:line](https://github.com/.../pull/N/files#diff-<hash>R<line>)\n# pr_url empty → path:line   (plain text, unchanged)\n```\n\nThe display text stays `path:line` so plain and linked tables look identical; only the URL goes in the link target. Pass `L` as the fourth argument for findings about removed code (default is `R`). Omit `<line>` for file-level findings to get a file-anchor link. Apply the same wrapping to `path:line` references inside the Tracked column (e.g. `TODO in foo.go:42`). Findings themselves follow `terse-comments`: concrete fix, optional `bug:`/`risk:`/`nit:`/`unsure:` prefix, no praise or restating the diff.\n\n---\n\n## Output Templates\n\n### Per-category findings\n\n```markdown\n| # | Finding | Severity | Tracked |\n|---|---------|----------|---------|\n| DOC1 | **Description.** Specific code reference (file:line or package). Explanation. | HIGH | — |\n| DOC2 | Description with code reference. | MEDIUM | TODO in file:line |\n```\n\n### Consolidated findings\n\n```markdown\n| Severity | ID | Finding | Source | Tracked |\n|----------|----|---------|--------|---------|\n| HIGH | 1 | Description with code references | DOC1, DOC5 | — |\n| MEDIUM | 2 | Description with code references | DOC3 | TODO in file:line |\n```\n\n**Tracked column values:** Use `—` for new findings. For already-captured findings: `TODO in file:line`, `FIXME in file:line`, `README`, `#123` (issue reference), etc.\n\n### Re-evaluation table (for follow-up reviews)\n\n```markdown\n| Finding | Status | What Changed |\n|---------|--------|--------------|\n| ~~1. Description~~ | FIXED | Brief explanation of the fix |\n| 2. Description | Still applicable | No changes |\n```\n\n---\n\n## Guidelines\n\n- Search the organization's codebase (Sourcegraph, GitHub) for existing documentation conventions before recommending changes.\n- Include effort estimates to help prioritize implementation.\n- When the user asks for a follow-up review, find the most recent review directory (`ls -d reviews/*/ 2>/dev/null | sort | tail -1`) containing `DOCUMENTATION-REVIEW.md`, re-evaluate all prior findings, and update with the re-evaluation table appended.\n- For detailed documentation quality dimensions, see [reference.md](reference.md).\n- **REVIEW.md integration**: If a `REVIEW.md` context section was provided by the review-all orchestrator (or exists at the repository root when running standalone), treat its rules as additional review criteria. \"Always check\" items are HIGH severity; \"Skip\" patterns exclude matching files from review scope.\n- Findings must cite probed evidence (`path:line`, grep output, command result), not pattern-matched suspicion. Per `~/.claude/rules/probe-not-assume.md`.","tags":["review","documentation","skill","issue","paultyng","agent-skills","ai-tools","claude-code","cursor","dotfiles"],"capabilities":["skill","source-paultyng","skill-review-documentation","topic-agent-skills","topic-ai-tools","topic-claude-code","topic-cursor","topic-dotfiles"],"categories":["skill-issue"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/paultyng/skill-issue/review-documentation","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add paultyng/skill-issue","source_repo":"https://github.com/paultyng/skill-issue","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (9,686 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:09:01.979Z","embedding":null,"createdAt":"2026-05-18T13:21:27.315Z","updatedAt":"2026-05-18T19:09:01.979Z","lastSeenAt":"2026-05-18T19:09:01.979Z","tsv":"'-1':932,1301 '/.../pull/n/files#diff-':1051 '/.claude/rules/probe-not-assume.md':1389 '/.claude/scripts/pr-deeplink.sh':1041 '/dev/null':1023,1298 '/documentation-review.md':837,844 '/internal/auth':184 '1':74,847,1185,1242 '123':1224 '2':271,851,1022,1193,1250,1297 '20':430 '3':280,759,855 '4':779,863 'abbrev':909 'abbrev-ref':908 'accord':388 'accur':65 'across':11,673 'action':52 'actual':492,721,731 'addit':1355 'affect':158 'alreadi':1212 'already-captur':1211 'also':941 'alway':1358 'analysi':252,296 'analyz':236 'anchor':1107 'api':264,514 'appear':621 'append':1318 'appli':1109 'applic':1253 'architectur':746 'argument':1087 'ask':28,1281 'audit':34 'avail':537,853 'b':552 'back':526 'base':103,940,942,944,951,982,983,985 'behavior':496 'block':833,886 'branch':92,113,903,971,973 'brief':1245 'bug':1134 'build':523 'c':657 'caller':1010 'captur':817,876,1213 'categori':1149 'chang':87,109,127,1241,1255,1270 'changelog':270 'check':38,60,335,359,366,503,575,676,699,717,727,1359 'cite':1374 'cli':708 'code':45,57,722,723,1092,1158,1169,1188,1196 'code-level':56 'codebas':84,209,411,1261 'column':1120,1204 'command':1381 'comment':14,16,260,333,373,377,444,468,470,487,581,585,592,617,619,636,1130 'commit':913,921,945,975,977,986 'complet':764 'concern':96 'concret':1131 'concurr':283 'condit':502 'config':713 'confirm':78 'consolid':770,856,1176 'const':455 'contain':168,1302 'content':488,639 'context':314,1332 'contradict':490 'contribut':740 'convent':1267 'criteria':1357 'cross':299,613 'cross-refer':612 'cross-referenc':298 'd':123,793,800,898,1295 'date':789,790,798,808,809,894 'datetim':893,970 'dedic':341 'dedupl':765 'default':129,214,1093 'deriv':157,200,222 'descript':265,623,632,643,989,1156,1167,1186,1194,1243,1251 'despit':634 'detail':1320 'detect':239 'diff':93,116,121,142,939,1144 'diff-bas':938 'diff-filt':120 'dimens':1323 'dir':795,802,805,816,836,843,880 'direct':533 'directori':167,177,191,786,1293 'display':1062 'diverg':640 'doc':13,33,40,206,251,332,433,450,467,469,486,520,542,548,653,661,756 'doc-com':331 'doc.go':253,446,529 'doc1':1155,1190 'doc2':1166 'doc3':1198 'doc5':1191 'document':3,5,31,46,49,62,241,295,371,392,556,735,890,1266,1321 'documentation-review.md':1303 'drift':630 'e.g':178,183,346,522,1121 'effort':1272 'empti':448,633,1055 'end':482 'endpoint':645 'enumer':403 'env':710 'error':501,524 'especi':593 'estim':1273 'etc':1227 'evalu':1230,1306,1316 'ever':337 'everi':362,1027 'everyth':213 'evid':1376 'exampl':22,255,505,517,724 'exclud':1366 'exist':63,243,370,611,637,678,696,1265,1343 'explan':1164,1246 'explicit':171 'explor':77,212,227 'export':451,513,732 'fail':521 'fall':525 'fan':324,343 'fan-out':323,342 'fi':812 'field':591,594,624 'file':20,88,110,128,150,163,170,187,197,219,238,249,254,258,267,312,398,510,532,562,573,606,672,688,692,704,1099,1106,1160,1174,1201,1217,1221,1368 'file-anchor':1105 'file-level':1098 'file/package':101 'filter':122,147,211 'find':54,368,384,546,651,754,767,857,990,1033,1089,1101,1125,1150,1152,1177,1181,1209,1214,1238,1288,1309,1372 'fix':777,865,1132,1244,1249 'fixm':1219 'fixme/hack/xxx':376 'flag':511,629,641,683,709,733 'follow':1127,1234,1285 'follow-up':1233,1284 'foo.go:42':1124 'fourth':1086 'full':83,208,410,922,978 'full-codebas':409 'func':454 'function':493,507 'function/type':728 'futur':322 'gap':736 'general':660 'generalpurpos':395,559,664 'get':126,1103 'gh':140,1015 'git':115,902,904,912,914,920,923,928,930,946,972,974,976,980 'github':1002,1263 'github.com':1050 'github.com/.../pull/n/files#diff-':1049 'given':189 'glob':598,669 'go':12,152,159,169,180,201,205,248,250,391,397,406,414,432,519,541 'goe':1077 'grep':1379 'guid':269,741 'guidelin':1256 'h':810,899 'h1':965 'haiku':352 'head':124,911,919,927 'header':823,827,850,875,953 'help':1275 'high':1165,1184,1362 'id':550,655,758,1180 'ident':1073 'implement':10,72,1277 'in-scop':309,569 'includ':195,534,1271 'individu':186 'inlin':862 'insid':1031,1117 'inspect':436 'instead':146 'integr':1328 'internal/auth':179 'investig':229,273,281,363 'invoc':207 'issu':379,1225 'item':1360 'json':1018 'key':512,714 'l':1083 'lack':516 'larg':734 'launch':272,277,316 'level':58,443,580,1100 'line':1029,1048,1057,1066,1115,1161,1175,1202,1218,1222,1378 'link':690,701,991,1039,1070,1080,1108 'list':102,220,307,407,415 'log':931 'longer':695 'look':1072 'ls':1294 'm':792,811,897,900 'main':131 'mark':386 'markdown':19,658,687,967,1038,1151,1178,1237 'match':1367,1386 'may':175 'md':154,266,671,962 'mechan':361 'medium':1171,1192 'messag':589 'met':321 'metadata':819,822,826,849,874 'method':584 'miss':440,458,577,582,586,642,685 'mkdir':813 'mode':994 'model':288,293,351,356 'multi':750 'multi-servic':749 'must':365,1373 'name':118,144,466,478,498,597,729 'name-on':117,143 'narrow':424 'near':878 'new':1208 'nit':1136 'note':326,375,539 'number':138 'omit':1096 'one':347,1025 'openapi':17,155,555,609,627,631 'openapi.yaml':262,601 'openapi.yml':261,600 'option':1133 'orchestr':1341 'order':772,778,866 'organ':1259 'oss':743 'output':438,785,840,889,961,1145,1380 'overlap':766 'overview':747 'p':814 'packag':160,181,193,202,223,349,404,419,427,442,449,1163 'package-level':441 'packages/directories':86 'parallel':276 'paramet':497,649 'parent':166 'pars':907,917,926,949 'pass':215,1082 'path':164,203,224,420,1028,1047,1056,1065,1114,1377 'paths/packages':172 'pattern':182,194,1365,1385 'pattern-match':1384 'per':290,329,348,353,1148,1388 'per-categori':1147 'per-symbol':328 'period':485 'place':955 'plain':1058,1068 'pr':90,111,137,141,993,1003,1004,1016,1042,1044,1053 'prais':1140 'precondit':319 'prefix':549,654,757,1138 'prepend':830,883 'presenc':334,358 'present':780,867 'pretti':933 'prior':1308 'priorit':53,1276 'probe':1375 'produc':51,768 'project':744 'prompt':399,563,665 'prose':303 'proto':15,153,257,553,561,572,616,618,635 'provid':1007,1335 'q':1020 'qualiti':6,1322 'r':1052,1095 'ran':543 're':1229,1305,1315 're-evalu':1228,1304,1314 'read':234,528,567 'readm':268,374,738,1223 'readme.md':677 'receiv':305 'recent':1291 'recommend':776,864,1269 'ref':910,943,952,984 'refer':59,135,381,614,706,1030,1116,1159,1170,1189,1197,1226 'referenc':300 'reference.md':1325,1326 'relat':700 'relev':149 'remov':1091 'render':832,885 'repo':675,681,752 'report':382,869 'repositori':1346 'request':108 'request/response':646 'requir':297,396,560 'resolut':881 'resolv':97,217,246,418,782 'restat':464,1142 'result':781,1382 'return':499,545,650,753,1024 'rev':906,916,925,948 'rev-pars':905,915,924,947 'review':2,4,32,47,50,784,788,794,796,797,801,804,806,807,815,835,842,879,997,1236,1287,1292,1296,1339,1356,1370 'review-al':1338 'review-document':1 'review.md':1327,1331 'risk':1135 'root':682,1347 'rout':294,357 'rpc':583 'rule':1353 'run':114,405,431,818,821,825,848,873,892,968,969,1013,1349 'run-metadata-head':824 'sampl':428,719 'scan':686 'schema':647 'scope':75,79,98,218,237,247,311,412,422,571,936,987,988,999,1371 'search':1257 'section':538,1333 'see':820,1324 'servic':579,751 'service-level':578 'service/method/message/field':259 'set':1046 'sever':774,1153,1179,1363 'sh':787,891,1040 'short':918,950 'signatur':301,494 'singl':462 'single-word':461 'skill' 'skill-review-documentation' 'skip':1364 'sonnet':289 'sort':1299 'sourc':531,1182 'source-paultyng' 'sourcegraph':1262 'spars':588 'spec':18,156,610,628 'specif':85,95,1157 'specifi':176 'split':338 'spot':698,716,726 'spot-check':697,715,725 'standalon':1014,1350 'start':474 'status':861,1239 'stay':67,1064 'still':1252 'structur':48,845 'subag':230,274,282,292,317,345,355,364,389,393,401,551,557,565,656,662,667,763 'subagent-model-rout':291,354 'subject':929,979,981 'success':544 'summar':760 'summari':854 'surfac':242 'suspicion':1387 'swagger':263 'swagger.json':605 'swagger.yaml':603 'swagger.yml':602 'symbol':330,452,477 'sync':8,43,69 'tabl':771,858,1034,1071,1231,1317 'tail':1300 'target':1081 'task':286 'templat':954,1146 'ters':1129 'terse-com':1128 'test':23,256,506 'test.go':509 'text':1059,1063 'titl':966 'todo':372,1122,1172,1199,1215 'tool':287,536,852 'top':958 'topic-agent-skills' 'topic-ai-tools' 'topic-claude-code' 'topic-cursor' 'topic-dotfiles' 'track':383,860,1119,1154,1183,1203 'tracker':380 'treat':1351 'tree':705 'trivial':460 'type':151,394,453,500,558,663 'u':895 'unchang':1060 'unclear':596 'uniqu':165 'unsur':1137 'updat':1311 'url':1005,1019,1021,1043,1045,1054,1076 'use':24,139,284,350,1206 'user':27,82,107,134,174,872,1280 'utc':901 'valu':1205 'var':456,711 'view':1017 'want':36 'whether':540 'whose':318 'within':244 'word':463 'workflow':73 'wrap':992,1026,1112 'write':838 'y':791,896","prices":[{"id":"3d789d0e-4fa8-4da5-9628-af363e72cd6f","listingId":"7810b245-8691-4b0f-91d2-e704cd551153","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"paultyng","category":"skill-issue","install_from":"skills.sh"},"createdAt":"2026-05-18T13:21:27.315Z"}],"sources":[{"listingId":"7810b245-8691-4b0f-91d2-e704cd551153","source":"github","sourceId":"paultyng/skill-issue/review-documentation","sourceUrl":"https://github.com/paultyng/skill-issue/tree/main/skills/review-documentation","isPrimary":false,"firstSeenAt":"2026-05-18T13:21:27.315Z","lastSeenAt":"2026-05-18T19:09:01.979Z"}],"details":{"listingId":"7810b245-8691-4b0f-91d2-e704cd551153","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"paultyng","slug":"review-documentation","github":{"repo":"paultyng/skill-issue","stars":8,"topics":["agent-skills","ai-tools","claude-code","cursor","dotfiles"],"license":"mit","html_url":"https://github.com/paultyng/skill-issue","pushed_at":"2026-05-18T18:26:54Z","description":"Personal Claude Code / Cursor agent skills, rules, and config","skill_md_sha":"18740f2331b8cd34737e86a247a770f32bb00ef5","skill_md_path":"skills/review-documentation/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/paultyng/skill-issue/tree/main/skills/review-documentation"},"layout":"multi","source":"github","category":"skill-issue","frontmatter":{"name":"review-documentation","description":"Review documentation quality and sync with implementation across Go doc comments, proto comments, OpenAPI specs, markdown files, and example tests. Use when the user asks for a documentation review, doc audit, or wants to check that docs are in sync with code."},"skills_sh_url":"https://skills.sh/paultyng/skill-issue/review-documentation"},"updatedAt":"2026-05-18T19:09:01.979Z"}}