Repository navigation
docs: add a docs-review skill - #7153
Abhishek-Mohan wants to merge 2 commits into
Conversation
2dc00b1 to
bfc0d2f
Compare
Add docs/source/contributor-guide/style_guide.md, which writes down the vocabulary from apache#4419 (pipeline membership, implementation language and data format), the rule for "native", how to name operators in prose, and the page conventions that the docs-review skill in apache#4420 cites. Each rule has a stable ID so that reviews can cite it. The guide follows the code where apache#4419 and the code differ: "Hybrid" keeps the meaning it already has in expressions.md, expressions are described separately from plan nodes, and "Arrow-native" is a claim about data format only. The Generated Content section names the generated text exactly, by the markers GenerateDocs fills in, including the config tables built from QueryPlanSerde and contrib config classes, and the cast tables built from CometCast. P18 covers attribution of third-party content, which apache#4420 lists among its checks. The guide's scope covers .doc strings in contrib config classes, and its vocabulary and accuracy rules also apply to doc comments, AGENTS.md and agent skills. Link the page from the contributor guide toctree and from AGENTS.md. Part of apache#4419. Generated-by: OpenCode
Add .ai/skills/review-comet-docs/SKILL.md, a sibling of review-comet-pr for documentation. It has three modes: PR mode reviews the docs a pull request changes, branch mode reviews a branch before it becomes a PR, and audit mode reviews an existing file or directory, including files not yet committed. The skill reads the documentation style guide on every run and cites its rule IDs rather than restating the rules. It finds the Apache remote and the PR's real base, reads everything from the reviewed revision, checks whether main has moved since, and checks only the added lines in PR and branch mode. Mechanical checks come first: vague "native" (including in Markdown italics), config keys (including keys built from a name at run time), operator names, links, anchors, images, external links, structure, redirects for moved pages, and version claims. Then it runs judgment checks, the most important being whether each claim, and each condition in it, still matches the code. Besides docs pages, it checks changed .doc strings, doc comments, AGENTS.md and agent skills. Findings are must-fix, should-fix, or nit, with nits dropped when the skill runs as part of a review-comet-pr review. It never edits files or posts comments. A short table of fixed cases says how to check the skill after changing it. In review-comet-pr, route docs changes to the new skill, mention documentation in its description, and remove "docs only" from the list of PRs it covers on its own. Fix two things in it that no longer match: `gh pr checks --failed` no longer exists, and the opt-in key is spark.comet.expression.<Name>.allowIncompatible. In review-comet-pr and review-comet-expression-pr, point at the style guide for exactly which docs text is generated. Closes apache#4420. Generated-by: OpenCode
bfc0d2f to
f7644b8
Compare
sunchao
left a comment
There was a problem hiding this comment.
Summary
- Prior state and problem
Comet’s general review skill covered documentation freshness but gave reviewers no shared terminology or procedure for checking documentation against the source. - Design approach
The stacked prerequisite publishes a style guide with stable rule IDs. The second commit adds one documentation-review skill for PRs, branches, and working-tree audits. - Correctness
The diff extractor mapped all 559 additions in this PR to the correct head lines. Separate fixtures showed where it can omit a file, mix revisions, miss broken navigation, or report a valid page as broken. - Compatibility analysis
Spark’sTreeNode.nodeNamestripsExecin all five pinned versions:3.4.3,3.5.9,4.0.4,4.1.3, and4.2.0. Comet’s window, exchange, and take-ordered overrides support the guide’s examples. The JVM shuffle writers also confirm its description of bufferingUnsafeRowbefore Arrow IPC encoding. Spark source - Key design decisions
The guide distinguishes pipeline membership, implementation language, and data format. Its distinction between generated tables and hand-written prose matchesGenerateDocsanddocs/build.sh. - Implementation sketch
The skill fetches review refs, computes a merge base, extracts added lines withgit diff -U0andawk, then compares names and claims with the reviewed source. - Performance
With PCRE-enabled Git, the config and operator inventories each took about 0.15 seconds on this checkout. The skill caps judgment checks at ten pages per run. No introduced P1/P2 execution-performance issue was found. - Design
A shared rulebook gives the three modes consistent criteria. The parent router omits two document types that the guide and child skill explicitly cover. - Abstraction & complexity
A review needs a stable base, head, and file list. Mutable refs and a shared shell-state file make those inputs depend on other invocations. The hand-written heading and navigation checks also lose information that the document parser provides. - Behavioral changes worth calling out
Relative tobranch-1.2, contributors gain a published guide and a documentation-review workflow. The parent skill also corrects the per-expressionallowIncompatiblekey and the failed-check filter. The changes affect contributor tooling and documentation. - Suggested improvements
Pin each invocation to verified commit IDs, enumerate its files through Git, and use the docs build’s target and heading rules. The inline reproductions provide focused regression cases for each failure.
Reviewed both commits and all six files at f7644b8f04f75bc207d8bf8056b129e200e56e53 against base 2b1c6a3938cbe1c4b2d0aa6383e64360569f877a, using merge base 5a50bd6f2777f3f20cefd929552d93dc6ab263c5. Routed skills were review-comet-pr, review-comet-docs, review-comet-expression-pr, and review-comet-shuffle-pr. All four specialist report digests matched. The PR was open and non-draft, with no existing reviews, conversation comments, inline comments, or review threads.
On the reviewed SHA, Label pull requests passed. Comet CI, CodeQL, and Check PR Title each concluded action_required with zero jobs. Comet CI run
Local validation covered git diff --check, disposable Git fixtures, tagged Spark source, and focused Sphinx 7.4.7/MyST 3.0.1 builds. The style guide rendered and all ten local link targets resolved. The full generated site, Spark/native suites, Prettier, and RAT were not run. Network policy blocked the external ASF licensing link check.
| touching the working tree. The leading `+` lets the fetch replace a ref after a force push. | ||
|
|
||
| ```bash | ||
| gh pr view <pr> --repo apache/datafusion-comet --json baseRefName,headRefOid,files |
There was a problem hiding this comment.
[P2] gh pr view --json files can silently truncate the list used to build <paths>. On a large PR, documentation after the first 100 files can escape review entirely. Enumerate the changed paths from the fetched merge base and head with git diff --name-only -z.
Evidence: With gh 2.98.0, Comet PR #5206 reported changedFiles=139 and returned 100 files. The paginated files API placed CometCoverageStatsSuite.scala at position 139. Its added class Scaladoc is in scope. PR #5206
| ```bash | ||
| gh pr view <pr> --repo apache/datafusion-comet --json baseRefName,headRefOid,files | ||
| git fetch "$R" "+refs/heads/<base>:refs/review/base-<pr>" "+pull/<pr>/head:refs/review/pr-<pr>" | ||
| HEAD_REF=refs/review/pr-<pr>; BASE=$(git merge-base refs/review/base-<pr> "$HEAD_REF") |
There was a problem hiding this comment.
[P2] Check that git merge-base succeeded before collecting added lines. A shallow checkout can fetch both tips and verify the correct head while still lacking their common ancestor. Deepen the history or report the comparison incomplete, and propagate failures from git diff.
Evidence: In a depth-one fixture, both refs fetched and the head matched. git merge-base exited 1, then the documented diff pipeline printed fatal: bad revision '', exited 0, and emitted zero lines. After deepening, it emitted the edit at docs/source/page.md:3.
| ```bash | ||
| gh pr view <pr> --repo apache/datafusion-comet --json baseRefName,headRefOid,files | ||
| git fetch "$R" "+refs/heads/<base>:refs/review/base-<pr>" "+pull/<pr>/head:refs/review/pr-<pr>" | ||
| HEAD_REF=refs/review/pr-<pr>; BASE=$(git merge-base refs/review/base-<pr> "$HEAD_REF") |
There was a problem hiding this comment.
[P2] Save the verified head commit ID for subsequent reads. HEAD_REF currently names a ref that another fetch of the same PR can advance. Even with private scratch files, an earlier review can then quote new source against its old line list.
Evidence: In a two-fetch fixture, the first head passed the equality check and its private list recorded page.md:2: old wording. After fetching the updated PR, git show through that same ref returned new wording. Reading the originally verified SHA still returned old wording.
| so save the variables you set and load them again in later calls: | ||
|
|
||
| ```bash | ||
| STATE="$(git rev-parse --git-dir)/review-comet-docs.env" |
There was a problem hiding this comment.
[P2] Give each invocation its own state file and carry that path into later shell calls. Two different PR reviews in one checkout currently overwrite review-comet-docs.env, so the first review can silently load the second PR’s base, head, and added lines.
Evidence: I interleaved the documented saves for PR 1 and PR 2 in a disposable checkout. The first review’s next shell successfully loaded refs/review/pr-2, base-2, and PR 2’s scratch path.
|
|
||
| ```bash | ||
| STATE="$(git rev-parse --git-dir)/review-comet-docs.env" | ||
| printf 'R=%s\nHEAD_REF=%s\nBASE=%s\nADDED=%s\n' "$R" "$HEAD_REF" "$BASE" "$ADDED" > "$STATE" |
There was a problem hiding this comment.
[P2] Serialize the saved values so paths containing spaces round-trip through a fresh shell. In a linked worktree, git rev-parse --git-dir can return an absolute path. The current printf writes that path as an unquoted assignment, preventing later checks from opening ADDED.
Evidence: In a linked worktree with its main checkout under repo with space, saving succeeded. Sourcing the resulting state file returned 127 and left ADDED empty.
| `_native execution_`, because `_` counts as a word character, so the patterns below use lookarounds. | ||
|
|
||
| **Lines to check.** In PR and branch mode, list the added lines with their file and line number, and | ||
| run the line checks below on this list only. In audit mode, run the line checks on the files with |
There was a problem hiding this comment.
[P2] Check incoming references when a PR removes or renames a heading or explicit label. The added-line list contains the new heading, while the link that the change breaks can be on an unchanged page. Search for references to the old target or validate the affected documents with Sphinx.
Evidence: A two-page fixture initially passed sphinx-build -W -n. Renaming ## Install to ## Setup made the only added line +## Setup. Sphinx then identified the unchanged index.md:3 link to howto.md#install as myst.xref_missing.
|
|
||
| ````bash | ||
| git show "${HEAD_REF}:<file>" | awk '/^[[:space:]]*(```|~~~)/{f=!f; next} !f && /^#{1,6} /{print FNR": "$0}' | ||
| git grep -n '<page-name>' <rev> -- 'docs/source/*.md' 'docs/source/*.rst' |
There was a problem hiding this comment.
[P2] Include untracked indexes in the audit-mode toctree search. An author can create a section index and child page before staging either. The audit inventories both files, but this command misses the valid navigation entry and can report it as must-fix.
Evidence: An untracked topic/index.md listed child inside its toctree. The documented git grep returned exit 1. Adding --untracked found the entry at topic/index.md:4.
| git grep -n '<page-name>' <rev> -- 'docs/source/*.md' 'docs/source/*.rst' | ||
| ```` | ||
|
|
||
| For the toctree check, search for the page's file name without `.md`. The pathspec matches every page, |
There was a problem hiding this comment.
[P2] Resolve a toctree entry relative to the document that contains it before counting it as a match. A basename such as index can match a valid entry for a different section, allowing a newly orphaned page to pass the navigation check.
Evidence: After adding second/index.md without a navigation entry, the prescribed search succeeded on first/index inside the root toctree. The base Sphinx build passed. The head build reported that second/index.md was not included in any toctree.
| tree in audit mode: | ||
|
|
||
| ````bash | ||
| git show "${HEAD_REF}:<file>" | awk '/^[[:space:]]*(```|~~~)/{f=!f; next} !f && /^#{1,6} /{print FNR": "$0}' |
There was a problem hiding this comment.
[P2] Use a format-aware heading check for .rst files. The selector includes reStructuredText, but the heading command recognizes only lines beginning with Markdown # markers. It cannot validate the title or section hierarchy of an RST page.
Evidence: The documented command exited successfully with zero headings for docs/source/user-guide/latest/index.rst. Docutils parsed lines 21–23 of that same file as the title Comet $COMET_VERSION User Guide.
| tree in audit mode: | ||
|
|
||
| ````bash | ||
| git show "${HEAD_REF}:<file>" | awk '/^[[:space:]]*(```|~~~)/{f=!f; next} !f && /^#{1,6} /{print FNR": "$0}' |
There was a problem hiding this comment.
[P2] Track the opening Markdown fence’s character and length, or read parsed heading nodes. Toggling the fence state on every triple delimiter treats a shorter fence inside a code example as its end and can report a shell comment as a second H1.
Evidence: In a page with one H1 and a four-backtick example containing a triple-backtick shell snippet, the command reported H1s at lines 1 and 5. The CommonMark parser returned only the heading at line 1.
Which issue does this PR close?
Closes #4420.
Rationale for this change
#4420 asks for a docs-focused sibling of
review-comet-prthat checks documentation against the #4419 style guide and against the code, and gives advice to a reviewer rather than editing or commenting.This PR is stacked on #7151, which adds the style guide the skill reads. The first commit here is #7151's style guide commit. I'll rebase once #7151 merges.
What changes are included in this PR?
New
.ai/skills/review-comet-docs/SKILL.md, with three modes:<pr-number>): reviews the docs a PR changes. It finds the Apache remote and the PR's real base branch, and fetches both into review refs without touching the working tree.<branch>): reviews a branch, tag, or commit before it becomes a PR.<path>): reviews an existing file or directory as it is now.What it reviews: Markdown under
docs/source,README.md, changed.doc(...)strings, and changed doc comments (Scaladoc, Javadoc, Rust///).How it works:
style_guide.mdon every run and cites rule IDs (T, N, O, P) instead of restating the rules. If the guide and the skill disagree, the guide wins.TODOmarkers. The commands usegit grep -Pandperl, because macOSgrephas no-Pandgit grep -Esilently ignores\b.Output: findings as must-fix, should-fix, or nit, each with
path:line, rule ID, quote, and suggested rewrite. It also reports the revisions it reviewed and any guide gaps. It never edits files, commits, pushes, or posts.Checking This Skill: a short table of fixed test cases with their expected results, to rerun after changing the skill or the guide.
review-comet-prchanges:docs/source/,README.md, and.doc(...)strings;The routing table is also edited by docs: add a scan contributor guide and a scan PR review skill #6052, so I'll rebase this row after whichever lands first.
Severity tiers. #4420 asked for must-fix, should-fix, and nit.
review-comet-prlater added "There is no third tier" (#5057). The skill keeps all three tiers for audits and for authors reviewing their own work. It drops nits when it runs as part of areview-comet-prreview, so that skill's review bar still decides what goes on a PR.Answers to #4420's open questions:
How are these changes tested?
After the test runs below, five independent AI reviews (GPT-6 Astra, Grok 4.7, Gemini 4 Argon, Claude Opus 5.5, GPT-6.1 Sol) ran the skill's commands on real pages and PRs. After two rounds, these findings are fixed:
createExecEnabledConfignames, and leaves out deprecated alternative names. It finds 136 keys on this branch.+refspec, and checks that the head it fetched is the PR's current head;index.md;review-comet-prandreview-comet-expression-prnow point to the guide for that;I ran every command in the current skill on this Mac against the #7151 branch.
Using the skill on its own PRs. I ran it with five models (Claude Opus 5.5, GPT-6.1 Sol, GPT-6 Astra, Grok 4.7, Gemini 4 Argon), each in a separate throwaway clone. Each model ran it twice: in PR mode on #7151, and on itself (PR mode on this PR, plus an audit of its own
SKILL.md).\bnative\bmisses Markdown italics such as_native execution_;++;~~~and indented code fences;_in slugs;review-comet-pr, it found two problems that were already onmain:gh pr checks --failedno longer exists;spark.comet.expr.allowIncompatibleisn't a real key.Earlier, I ran the skill with subagents on real pages and PRs, fixed what the runs exposed, and re-ran two of them.
plugin_overview.mdunderstanding-comet-plans.mdCometNativeScan, or config keystimezones.md(contributor guide)datasources.md.docstring claim more than the code does, and "unlike the switches above" contradicts line 57.The test runs also changed the skill:
git grep -Peverywhere. macOSgrephas no-P, andgit grep -Esilently ignores\b.On these pages, a round-2 run took 10-15 tool calls.
Sample output: PR mode on #6786 (round 2, shortened)
Scope. PR mode,
refs/review/pr-6786. Revieweddatasources.md:77-86and the new.doc(...)forspark.comet.convert.broadcastBuildSide.enabled, plus the code diff inCometExecRule.scala.Must-fix
datasources.md:77-80, P16 (also N1, N3): "a file or V2 scan Comet cannot read natively … the whole join runs natively".shouldBridgeUnsupportedScanis reached only from the fallback branch, so CSV, JSON, and Parquet scans are not covered. The conversion also needs the broadcast exchange and join configs, andclearWastedBuildSideBridgescan undo it. Suggested: "…a scan of a file format other than Parquet, JSON or CSV … so the join can run in the Comet pipeline."CometConf.scala:1225-1228, P16: the same overclaim in the.docstring, which is published inconfigs.md.datasources.md:81, P16: "on by default, unlike the switches above".spark.comet.convert.oneRowRelation.enabledis also on by default, and line 58 says so. Suggested: "which is on by default."Already on the page:
datasources.md:62"not generate natively" (N1);:63"Comet's native cache scan" (N3).Sample output: audit of timezones.md (round 2, shortened)
Must-fix
timezones.md:115, P13: listsToJsonandToCsv, but the expression classes areStructsToJsonandStructsToCsv.timezones.md:144-145, P16 and N1: "date_formatruns natively only in UTC sessions".CometDateFormatalso takes the Rust path in non-UTC sessions whenallowIncompatibleis set.Should-fix: four N1 uses (lines 198, 219, 235, 258), and P8 on line 187 ("Spark 3.x", "Spark 4.0+").
Nit: mention
spark.comet.testing.strictTimestampLabels.enabledin the testing section.Guide gaps: heading case is not covered.
AI assistance: OpenCode helped write the skill and ran the test reviews. The findings above came from those runs.