Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .claude/pr-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# PR review prompt

Review the PR, file, or diff specified by the user as an experienced technical writer for Datadog documentation.

## Audience

Developers and DevOps engineers implementing observability solutions. They're technical, busy, and want to get things done. They may be new to Datadog or experienced users adding new capabilities.

## Review Focus Areas

### 1. Clarity & User Journey
- Is the content clear for someone arriving via the expected navigation path?
- Does it make sense in context, or does it assume too much/too little?
- Can users complete the task without leaving the page unnecessarily?
- Is there a clear "verify it works" moment or success criteria?

### 2. Accuracy & Completeness
- Are code examples complete and copy-pasteable?
- Are prerequisites explicit and linked where needed?
- Are there gaps that would block a user from succeeding?
- Is technical information accurate?

### 3. Structure & Scannability
- Does it follow a logical progression?
- Can users skim to find what they need?
- Are headings descriptive and actionable?
- Is the page in the right section of the docs (information architecture)?

### 4. Frontmatter & Metadata
- Is there a `description` for SEO/AI ingestion?
- Are `further_reading` links relevant and non-duplicative?
- Are reference links free of duplicates or unused entries?
- Does the title match how it's linked from other pages?

## Style Guide (Vale Rules)

Check for these substitutions:

| Don't use | Use instead |
|-----------|-------------|
| once you/once the | after you/after the |
| refer to/visit | see |
| fine-tune | customize, optimize, or refine |
| ensure/ensures | helps ensure, or rephrase |
| leverage | use, apply, take advantage of |
| utilize | use |
| in order to | to |
| via | with, through |
| drill down | examine, investigate, analyze |
| Note that | **Note**: |

Remove filler words and unsupported claims:
- easy, easily, simple, simply, just
- please
- seamless, seamlessly
- obvious, obviously
- quick, quickly
- very

Other style rules:
- Use American English (en_US)
- "See" should be lowercase after a comma
- Avoid temporal words that age poorly: currently, now, will, won't
- Use imperative voice for instructions ("Run the command" not "You should run the command")
- Be direct and concise—developers want facts, not fluff

For complete style guidance, see [CONTRIBUTING.md](../CONTRIBUTING.md) in the repository.
All vale rules can be found in the [datadog-vale](https://github.com/DataDog/datadog-vale) repository.

## Review Output Format

**Use inline comments for all feedback:**
- For each specific issue, suggestion, or style violation, create an inline comment on the exact line using the `mcp__github_inline_comment__create_inline_comment` tool
- Include the issue type in your comment: "**Issue**:", "**Suggestion**:", or "**Style**:"
- **When you have a specific fix to propose, use GitHub's suggestion format so the author can apply it with one click:**
```suggestion
corrected text or code here
```
- Provide ONE clear suggestion per comment - don't offer multiple alternatives or variations
- Be specific about what to change and why

**After posting all inline comments:**
- Keep your final text output minimal (just "Review complete" or similar)
- Do NOT output a verbose summary - the inline comments contain all the feedback

## Review Principles

- Be direct and actionable, not pedantic
- Distinguish between blockers and nice-to-haves
- Consider the realistic user path, not just the standalone page experience
- Focus on what helps users succeed
- Don't nitpick formatting if the content is clear
- Suggest fixes, not just problems
8 changes: 8 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,11 @@ content/en/**/*.mdoc.md @DataDog/cdocs-rev
layouts/shortcodes/**/*.mdoc.md @DataDog/cdocs-reviewers @DataDog/documentation
content/.gitignore @DataDog/cdocs-reviewers @DataDog/documentation
content/en/dd_e2e @DataDog/docs-dev

# AI PR review pipeline — security boundary, see file headers.
# Sole ownership keeps the security model from being changed
# without SDLC Security review. `.claude/pr-review.md` is the
# review instructions only and stays on the default ownership.
.github/workflows/claude_review.yml @DataDog/sdlc-security
.github/scripts/ @DataDog/sdlc-security
.github/schemas/create-review.json @DataDog/sdlc-security
34 changes: 34 additions & 0 deletions .github/schemas/create-review.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "create-review.json",
"title": "Claude review payload",
"description": "Slice of GitHub's `POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews` request body, sourced from github/rest-api-description (descriptions/api.github.com/api.github.com.json). The per-comment shape is copied from upstream with workflow-specific tightenings (see below); top-level constraints are tightened so the workflow controls what reaches the API: `commit_id` is omitted because the workflow injects it, `event` is locked to COMMENT to prevent the model from approving or requesting changes, and `comments` is capped at 100 entries as a sanity bound. Each comment requires `line` OR `position` — upstream lists both as optional, but GitHub's runtime requires one of them for inline comments; catching the absence here turns an all-or-nothing API rejection into a clean per-run schema failure. `side` and `start_side` are constrained to LEFT/RIGHT — upstream publishes them as plain strings with an example value, but the runtime API rejects any other value and would fail the entire review; the enum catches typos like `right` at the schema layer.",
"type": "object",
"required": ["body", "event", "comments"],
"additionalProperties": false,
"properties": {
"body": { "type": "string" },
"event": { "type": "string", "enum": ["COMMENT"] },
"comments": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"required": ["path", "body"],
"anyOf": [
{ "required": ["line"] },
{ "required": ["position"] }
],
"properties": {
"path": { "type": "string" },
"body": { "type": "string" },
"position": { "type": "integer" },
"line": { "type": "integer" },
"side": { "type": "string", "enum": ["LEFT", "RIGHT"] },
"start_line": { "type": "integer" },
"start_side": { "type": "string", "enum": ["LEFT", "RIGHT"] }
}
}
}
}
}
8 changes: 8 additions & 0 deletions .github/scripts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# npm ci writes the install tree here at runtime; never committed.
node_modules/

# The repo-level .gitignore excludes package-lock.json files everywhere.
# Override that for this directory: the lockfile is what `npm ci` uses
# to verify SHA-512 integrity of ajv and its transitive dependencies, so
# it MUST be committed.
!package-lock.json
65 changes: 65 additions & 0 deletions .github/scripts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .github/scripts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"private": true,
"dependencies": {
"ajv": "8.20.0"
}
}
37 changes: 37 additions & 0 deletions .github/scripts/scan_secrets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Secret-pattern scanner shared by the review and post jobs.
//
// Regex list mirrors the claude-code-action sanitizer (GitHub
// token families) plus Anthropic token families. Add new patterns
// by appending here — every pattern is applied to every string
// reached by `hasToken`.

"use strict";

const TOKEN_PATTERNS = [
/ghp_[A-Za-z0-9_]{36,}/,
/gho_[A-Za-z0-9_]{36,}/,
/ghs_[A-Za-z0-9_]{36,}/,
/ghr_[A-Za-z0-9_]{36,}/,
/ghu_[A-Za-z0-9_]{36,}/,
/github_pat_[A-Za-z0-9_]{82,}/,
/sk-ant-api[0-9]{2}-[A-Za-z0-9_\-]+/,
/sk-ant-oat[0-9]{2}-[A-Za-z0-9_\-]+/,
/sk-ant-sid[0-9]{2}-[A-Za-z0-9_\-]+/,
/sk-ant-[A-Za-z0-9_\-]{20,}/,
/sk-proj-[A-Za-z0-9_\-]{20,}/,
/sk-svcacct-[A-Za-z0-9_\-]{20,}/,
/sk-[A-Za-z0-9]{48,}/,
];

function hasToken(value) {
if (typeof value === "string") {
return TOKEN_PATTERNS.some((p) => p.test(value));
}
if (Array.isArray(value)) return value.some(hasToken);
if (value && typeof value === "object") {
return Object.values(value).some(hasToken);
}
return false;
}

module.exports = { TOKEN_PATTERNS, hasToken };
31 changes: 31 additions & 0 deletions .github/scripts/validate_review.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Validate Claude's review JSON against `.github/schemas/create-review.json`
// using Ajv. The workflow runs `npm install ajv` before invoking github-
// script so this module can `require("ajv")` via standard Node resolution
// (walks up to $GITHUB_WORKSPACE/node_modules).

"use strict";

const fs = require("node:fs");
const path = require("node:path");
const Ajv = require("ajv");

const SCHEMA_PATH = path.join(__dirname, "..", "schemas", "create-review.json");
const SCHEMA = JSON.parse(fs.readFileSync(SCHEMA_PATH, "utf8"));

// strictRequired: false — Ajv's default strict mode complains when
// `required` appears inside `anyOf`/`oneOf` without redeclaring the
// `properties` block at that level. Our schema uses
// `anyOf: [{required:[line]},{required:[position]}]` to enforce
// GitHub's "inline comments need coordinates" runtime rule without
// duplicating the property declarations.
const ajv = new Ajv({ allErrors: false, strict: true, strictRequired: false });
const ajvValidate = ajv.compile(SCHEMA);

function validate(obj) {
if (ajvValidate(obj)) return null;
const e = ajvValidate.errors?.[0] ?? {};
const where = e.instancePath || "$";
return `${where} ${e.message || "invalid"}`.trim();
}

module.exports = { validate, SCHEMA };
Loading
Loading