feat: implement design agent for ui reviews#824
Conversation
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Adds a new DESIGN_GUIDELINES.md document intended to act as the single source of truth for Keploy Docs UI/design standards and as a ruleset for an automated PR review agent.
Changes:
- Introduces an extensive design system reference (tokens, layout, components, accessibility, performance).
- Adds a detailed, severity-tagged PR review checklist to enforce UI consistency across docs/site changes.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | Content reading area | `max-width: 860px` | | ||
| | Sidebar width (default) | `260px` | | ||
| | Sidebar width (large ≥1400px) | `280px` | | ||
| | Sidebar width (tablet 997–1200px) | `200px` | | ||
| | Sidebar width (medium 997–1100px) | `180px` | | ||
| | TOC width (default) | `250px` | | ||
| | TOC width (tablet) | `140–180px` | | ||
| | TOC width (large) | `200–240px` | | ||
|
|
||
| > **Rule:** The `860px` content max-width is a reading-width optimization (~70–80 characters per line at 18px base). Do not widen this. | ||
|
|
There was a problem hiding this comment.
The guidelines assert a hard max-width: 860px reading area and treat widening it as a blocker, but there’s no 860px max-width defined anywhere in src/ (and article.markdown is currently set to max-width: 100% in src/css/custom.css). If 860px is the intended standard, it should be implemented in CSS (and referenced from the actual source of truth); otherwise, the guideline should reflect the real layout constraints used today.
| | Context | Value | | ||
| |---------|-------| | ||
| | Content reading area | `max-width: 860px` | | ||
| | Sidebar width (default) | `260px` | |
There was a problem hiding this comment.
Sidebar width values here don’t match the current implementation: src/css/custom.css sets --doc-sidebar-width: 275px !important; (not 260px). If 260px is the desired standard, the CSS variable should be updated accordingly; otherwise, adjust these numbers so the guideline reflects what contributors will actually see.
| | Sidebar width (default) | `260px` | | |
| | Sidebar width (default) | `275px` | |
| | C4 | Paragraph `margin-bottom` is `1.5rem` — not reduced | ⚠️ Major | | ||
| | C5 | Code block `margin` is `2rem 0` — not removed | ℹ️ Minor | | ||
| | C6 | Sidebar width is `260px` (default) — not overridden without responsive justification | ⚠️ Major | | ||
| | C7 | No custom `width` or `max-width` added to `<article>` or `.markdown` | ❌ Blocker | |
There was a problem hiding this comment.
Checklist item C7 (“No custom width or max-width added to <article> or .markdown”) doesn’t match the current implementation: src/css/custom.css sets article.markdown { max-width: 100%; width: 100%; } and also forces main/doc containers to width: 100% !important;. If this checklist is meant to be enforced, it should be reworded to the real intent (e.g., “no fixed widths / no narrowing max-widths” or “no new layout overrides”) so it doesn’t fail against the existing baseline styling.
| | C7 | No custom `width` or `max-width` added to `<article>` or `.markdown` | ❌ Blocker | | |
| | C7 | No fixed widths, narrowing `max-width`s, or new layout overrides added to `<article>`, `.markdown`, or doc containers beyond the baseline full-width styling | ❌ Blocker | |
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.github/workflows/design-review.yml
Outdated
| run: | | ||
| cd .github/scripts | ||
| npm init -y --quiet | ||
| npm install @anthropic-ai/sdk@latest --save --quiet |
There was a problem hiding this comment.
This workflow installs @anthropic-ai/sdk@latest at runtime. Using @latest makes runs non-reproducible and can break unexpectedly (e.g., if the SDK switches to ESM-only or changes APIs). Pin the dependency to a known-good version (and ideally commit a small package.json/lockfile under .github/scripts or install from the repo root).
| npm install @anthropic-ai/sdk@latest --save --quiet | |
| npm install @anthropic-ai/sdk@0.32.1 --save-exact --quiet |
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] |
There was a problem hiding this comment.
The workflow runs on all pull requests (no paths filter). This will run and attempt to comment on PRs that change non-design code, creating noise and extra CI load. Consider adding a paths: filter under pull_request similar to the push trigger, so it only runs when design-relevant files change.
| types: [opened, synchronize, reopened] | |
| types: [opened, synchronize, reopened] | |
| paths: | |
| # Only run on pull requests if design-relevant files changed | |
| - "**.css" | |
| - "**.scss" | |
| - "**.mdx" | |
| - "**.md" | |
| - "**.tsx" | |
| - "**.jsx" | |
| - "**.js" | |
| - "**.ts" |
.github/scripts/design-review.js
Outdated
| const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; | ||
|
|
||
| if (!ANTHROPIC_API_KEY) { | ||
| console.error("ERROR: ANTHROPIC_API_KEY environment variable is not set."); | ||
| process.exit(1); | ||
| } |
There was a problem hiding this comment.
design-review.js exits immediately when ANTHROPIC_API_KEY is missing. On PRs from forks (where secrets aren’t available) this will fail the workflow even when there are no design-relevant changes. Consider moving the ANTHROPIC_API_KEY requirement check to after you’ve determined there are relevant files to review, and/or guard the workflow so it only runs when the secret is present / PR is from the same repo.
| // Step 2: Filter to design-relevant files | ||
| const relevantFiles = filterFiles(changedFiles); | ||
| console.log(`Design-relevant files: ${relevantFiles.length}`); | ||
|
|
||
| if (relevantFiles.length === 0) { | ||
| console.log("No design-relevant files changed. Skipping review."); | ||
| await postComment( | ||
| "## Keploy Design Review\n\n✅ No design-relevant files changed in this diff (no `.css`, `.scss`, `.mdx`, `.md`, `.tsx`, `.jsx`, or `.js` files). Nothing to review." | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| // Step 3: Build the prompt | ||
| console.log("Building review prompt..."); | ||
| const { system, user } = buildPrompt(diff, relevantFiles); | ||
|
|
There was a problem hiding this comment.
You compute relevantFiles, but still pass the full unified diff into buildPrompt(...). This means the agent can flag issues in non-relevant files (including its own .github/scripts/*) whenever at least one relevant file exists. Filter the diff down to hunks for relevantFiles (or fetch per-file diffs) before building the prompt.
| const IGNORED_PATHS = [ | ||
| "node_modules/", | ||
| "build/", | ||
| ".docusaurus/", | ||
| "package-lock.json", | ||
| "yarn.lock", | ||
| "pnpm-lock.yaml", | ||
| ]; |
There was a problem hiding this comment.
filterFiles() currently allows any .js/.ts/.md files, including CI/scripts under .github/. That will cause the design agent to review non-UI automation code (and potentially comment on its own implementation). Add .github/ (and possibly DESIGN_GUIDELINES.md) to IGNORED_PATHS, or restrict allowed paths to actual site sources like src/, docs/, and versioned_docs/.
.github/scripts/get-diff.js
Outdated
| .get(options, (res) => { | ||
| let data = ""; | ||
| res.on("data", (chunk) => (data += chunk)); | ||
| res.on("end", () => resolve(data)); |
There was a problem hiding this comment.
fetchPRDiff() resolves the response body without checking res.statusCode. If the API returns a 4xx/5xx (e.g., permissions/rate-limit), you’ll send an error payload to the LLM and/or mis-detect changed files. Check the status code and reject(...) with a helpful error when it’s not 2xx.
| res.on("end", () => resolve(data)); | |
| res.on("end", () => { | |
| const { statusCode } = res; | |
| if (statusCode < 200 || statusCode >= 300) { | |
| const responseSnippet = data.trim().slice(0, 500); | |
| reject( | |
| new Error( | |
| `Failed to fetch PR diff from GitHub API (status ${statusCode}). ` + | |
| `Check that GITHUB_TOKEN has access to ${owner}/${repo}, PR_NUMBER is correct, and you are not being rate limited.` + | |
| (responseSnippet ? ` Response: ${responseSnippet}` : "") | |
| ) | |
| ); | |
| return; | |
| } | |
| resolve(data); | |
| }); |
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Keploy Design Review✅ No design-relevant files changed in this diff. Nothing to review. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| paths: | ||
| - "**.css" | ||
| - "**.scss" | ||
| - "**.mdx" | ||
| - "**.md" | ||
| - "**.tsx" | ||
| - "**.jsx" | ||
| - "**.js" | ||
| - "**.ts" | ||
|
|
There was a problem hiding this comment.
Workflow runs on pull_request while checking out and executing .github/scripts/design-review.js, but it also injects ANTHROPIC_API_KEY. For PRs from branches within the same repo, this lets a PR modify the script and exfiltrate secrets at runtime. Consider switching to pull_request_target and checking out the base ref (trusted workflow code), or avoid using secrets on PR events and instead run only on protected branches / workflow_dispatch.
.github/scripts/prompt.js
Outdated
| // Max characters of diff to send, keeps tokens under control | ||
| const MAX_DIFF_CHARS = 80000; | ||
|
|
||
| function loadGuidelines() { | ||
| const guidelinesPath = path.resolve( | ||
| __dirname, | ||
| "../../DESIGN_GUIDELINES.md" | ||
| ); | ||
| if (!fs.existsSync(guidelinesPath)) { | ||
| throw new Error( | ||
| "DESIGN_GUIDELINES.md not found at repo root. Cannot run design review." | ||
| ); | ||
| } | ||
| return fs.readFileSync(guidelinesPath, "utf8"); | ||
| } |
There was a problem hiding this comment.
prompt.js truncates the diff but not DESIGN_GUIDELINES.md. Since the guidelines file is already very large and likely to grow, the combined prompt can exceed model/context limits or increase latency/cost significantly. Consider truncating/summarizing guidelines (e.g., include only Section 11 rule table + required token/value tables) or enforce a max guideline character limit similar to MAX_DIFF_CHARS.
.github/scripts/design-review.js
Outdated
| const message = await client.messages.create({ | ||
| model: "claude-sonnet-4-6", | ||
| max_tokens: 4096, | ||
| messages: [ |
There was a problem hiding this comment.
The model name is hard-coded (claude-sonnet-4-6). To avoid workflow breakage when models are renamed/deprecated, make this configurable via an env var (with a sane default) and include the model name in error output when requests fail.
.github/scripts/design-review.js
Outdated
| console.error("ERROR: ANTHROPIC_API_KEY environment variable is not set."); | ||
| process.exit(1); |
There was a problem hiding this comment.
If ANTHROPIC_API_KEY is missing, the script exits with code 1, which will fail checks on fork PRs (where secrets are unavailable) even though GITHUB_TOKEN can still be used to post a clear “could not run” comment. Consider posting a non-failing comment explaining that the design review was skipped due to missing credentials, and exit 0.
| console.error("ERROR: ANTHROPIC_API_KEY environment variable is not set."); | |
| process.exit(1); | |
| console.log( | |
| "ANTHROPIC_API_KEY is not set. Skipping design review and posting a comment so maintainers can rerun after configuring credentials." | |
| ); | |
| await postComment( | |
| "## Keploy Design Review\n\n⚪ Design review was skipped because `ANTHROPIC_API_KEY` is not available in this workflow run. This commonly happens on fork pull requests where secrets are not exposed. If you need a review, ask a maintainer to rerun the workflow with the required credentials." | |
| ); | |
| return; |
| /** | ||
| * Find and delete any previous design review comment on the PR | ||
| * so we don't accumulate stale comments. | ||
| */ | ||
| async function deletePreviousReviewComment(owner, repo) { | ||
| const listPath = `/repos/${owner}/${repo}/issues/${PR_NUMBER}/comments`; | ||
|
|
||
| const comments = await new Promise((resolve, reject) => { | ||
| const options = { | ||
| hostname: "api.github.com", | ||
| path: listPath, | ||
| method: "GET", | ||
| headers: { | ||
| Authorization: `Bearer ${GITHUB_TOKEN}`, | ||
| Accept: "application/vnd.github.v3+json", | ||
| "User-Agent": "keploy-design-review-agent", | ||
| }, | ||
| }; | ||
|
|
||
| https | ||
| .get(options, (res) => { | ||
| let data = ""; | ||
| res.on("data", (c) => (data += c)); | ||
| res.on("end", () => resolve(JSON.parse(data))); | ||
| }) | ||
| .on("error", reject); | ||
| }); | ||
|
|
There was a problem hiding this comment.
deletePreviousReviewComment calls the PR comments API without pagination; GitHub returns only the first page by default, so an older “Keploy Design Review” comment may not be found/deleted on large PRs. Consider adding ?per_page=100 and iterating through Link headers (or looping pages) until the matching bot comment is found/removed.
| /** | |
| * Find and delete any previous design review comment on the PR | |
| * so we don't accumulate stale comments. | |
| */ | |
| async function deletePreviousReviewComment(owner, repo) { | |
| const listPath = `/repos/${owner}/${repo}/issues/${PR_NUMBER}/comments`; | |
| const comments = await new Promise((resolve, reject) => { | |
| const options = { | |
| hostname: "api.github.com", | |
| path: listPath, | |
| method: "GET", | |
| headers: { | |
| Authorization: `Bearer ${GITHUB_TOKEN}`, | |
| Accept: "application/vnd.github.v3+json", | |
| "User-Agent": "keploy-design-review-agent", | |
| }, | |
| }; | |
| https | |
| .get(options, (res) => { | |
| let data = ""; | |
| res.on("data", (c) => (data += c)); | |
| res.on("end", () => resolve(JSON.parse(data))); | |
| }) | |
| .on("error", reject); | |
| }); | |
| function parseNextLink(linkHeader) { | |
| if (!linkHeader) { | |
| return null; | |
| } | |
| const links = linkHeader.split(","); | |
| for (const link of links) { | |
| const match = link.match(/<([^>]+)>;\s*rel="([^"]+)"/); | |
| if (match && match[2] === "next") { | |
| const nextUrl = new URL(match[1]); | |
| return `${nextUrl.pathname}${nextUrl.search}`; | |
| } | |
| } | |
| return null; | |
| } | |
| async function fetchAllIssueComments(owner, repo) { | |
| const comments = []; | |
| let nextPath = `/repos/${owner}/${repo}/issues/${PR_NUMBER}/comments?per_page=100`; | |
| while (nextPath) { | |
| const pageComments = await new Promise((resolve, reject) => { | |
| const options = { | |
| hostname: "api.github.com", | |
| path: nextPath, | |
| method: "GET", | |
| headers: { | |
| Authorization: `Bearer ${GITHUB_TOKEN}`, | |
| Accept: "application/vnd.github.v3+json", | |
| "User-Agent": "keploy-design-review-agent", | |
| }, | |
| }; | |
| https | |
| .get(options, (res) => { | |
| let data = ""; | |
| res.on("data", (c) => (data += c)); | |
| res.on("end", () => { | |
| if (res.statusCode < 200 || res.statusCode >= 300) { | |
| reject( | |
| new Error( | |
| `GitHub API error ${res.statusCode} while listing PR comments. Please verify the repository, PR number, and token permissions, then retry. Response: ${data}` | |
| ) | |
| ); | |
| return; | |
| } | |
| let parsedComments; | |
| try { | |
| parsedComments = data.length > 0 ? JSON.parse(data) : []; | |
| } catch (error) { | |
| reject( | |
| new Error( | |
| `GitHub API returned invalid JSON while listing PR comments. Please retry the workflow, and if the issue persists inspect the API response body. Response: ${data}` | |
| ) | |
| ); | |
| return; | |
| } | |
| nextPath = parseNextLink(res.headers.link); | |
| resolve(Array.isArray(parsedComments) ? parsedComments : []); | |
| }); | |
| }) | |
| .on("error", reject); | |
| }); | |
| comments.push(...pageComments); | |
| } | |
| return comments; | |
| } | |
| /** | |
| * Find and delete any previous design review comment on the PR | |
| * so we don't accumulate stale comments. | |
| */ | |
| async function deletePreviousReviewComment(owner, repo) { | |
| const comments = await fetchAllIssueComments(owner, repo); |
| const botComments = comments.filter( | ||
| (c) => | ||
| c.user.type === "Bot" && | ||
| c.body.includes("Keploy Design Review") | ||
| ); |
There was a problem hiding this comment.
The deletion filter matches any Bot comment containing “Keploy Design Review”, which could delete comments from other bots (or future automation) that happen to include that phrase. Consider narrowing this to the specific bot identity (e.g., c.user.login === 'github-actions[bot]' and/or a unique HTML comment marker in the body) before deleting.
| ### 4.5 Admonitions / Callout Boxes | ||
|
|
||
| **Purpose:** Surface important notes, tips, warnings, dangers, and info contextually. | ||
|
|
||
| **5 Types and When to Use:** | ||
|
|
||
| | Type | Keyword | Use For | | ||
| |------|---------|---------| | ||
| | `:::note` | Note | Supplementary context, caveats | | ||
| | `:::tip` | Tip | Best practices, helpful shortcuts | | ||
| | `:::warning` / `:::caution` | Warning | Potential issues, gotchas | | ||
| | `:::danger` | Danger | Destructive actions, data loss risks | | ||
| | `:::info` | Info | Keploy-specific callouts, feature notes | | ||
|
|
||
| **Visual Rules:** | ||
| ``` | ||
| border-radius: 14px | ||
| border: 1px solid [type-color at 20% opacity] | ||
| background: gradient 135deg, [type-color at 8% → 2%] | ||
| left-accent: 4px vertical bar with type gradient | ||
| padding: 1rem 1.25rem | ||
| margin: 1.5rem 0 | ||
| heading size: 0.875rem, weight 700, uppercase, letter-spacing 0.04em | ||
| content size: 0.9375rem, line-height 1.7 | ||
| ``` | ||
|
|
||
| **Do's:** | ||
| - ✅ Use the correct semantic type — don't use `:::warning` as a general note | ||
| - ✅ Keep admonition content concise (2–4 lines) | ||
| - ✅ Use the built-in Docusaurus `:::type` syntax — never a custom `<div>` for callouts |
There was a problem hiding this comment.
The guidelines mandate Docusaurus :::note/:::tip admonitions, but the existing docs in this repo consistently use GitHub-style admonitions (e.g., > [!NOTE] in versioned_docs/version-4.0.0/keploy-cloud/kubernetes.md). If this is meant to be an enforcement source of truth, update the admonition rules/examples to match the repo’s actual Markdown convention (or document an explicit migration plan).
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Design Review Agent (Docs), Production-hardened PR reviewer
This PR adds a security-hardened Design Review Agent that can be triggered by trusted maintainers to review design/UI-relevant PR diffs and upsert a single PR comment with a strict, machine-parseable verdict.
Key outcomes:
design-agent/scripts/design_review.py) + a GitHub Actions workflow (.github/workflows/design-review.yml).keploy/landing-page) with docs-repo-specific guidelines (generated from this repo’s actual styling + theme code).What changed
New agent runtime
design-agent/scripts/design_review.pyPR_NUMBER, plushead.sha/head.repo.full_name).pulls/{pull_number}/files).design-agent/DOCS_DESIGN_GUIDELINES.mdfrom diff payload (prevents circular self-review).patch == null/ empty): postsMANUAL_REVIEW_REQUIREDand skips Anthropic.ALLOW_EXTERNAL_PR_REVIEWnot true: postsSKIPPEDand returns.<!-- design-agent-review-comment -->pr.head.sha(blob links for exact reviewed versions).New workflow
.github/workflows/design-review.ymlpull_request,issue_comment,workflow_dispatch.pull-requests: writeissues: writecontents: readGITHUB_TOKEN: ${{ github.token }}(notsecrets.GITHUB_TOKEN)./design-reviewOWNER/MEMBER/COLLABORATORworkflow_dispatchinputgithub.event.inputs['pr-number']).head.sha,head.repo.full_name, base repo, default branch) via GitHub API.pr.head.shaRepo-specific guidelines (generated from this repo)
design-agent/DOCS_DESIGN_GUIDELINES.mdpackage.json(stack/deps)docusaurus.config.js(Docusaurus config, typography loading)tailwind.config.js(Tailwind usage, tokens, dark mode strategy, preflight disabled)src/css/custom.css(Infima variable overrides, fonts, dark mode selectors, layout hotfixes)src/theme/**andsrc/components/**(patterns used in actual code)Dependencies
design-agent/requirements.txtanthropic==0.40.0PyGithub==2.1.1Documentation
design-agent/README.mdWhy this approach
Why a Python script (instead of JS-only)
The agent is implemented as a single Python entrypoint for reliability + security hardening:
Note:
PyGithubis pinned per dependency policy for reproducibility and future maintenance flexibility, even though the current implementation uses stdlib HTTP utilities for maximum transparency/control.Why fetch common guidelines at runtime
The shared design policy lives in a private repo (
keploy/landing-page) and must not be copied into public docs. Fetching via the GitHub REST “contents” endpoint:COMMON_GUIDELINES_REF, defaultmain)DESIGN_COMMONS_TOKENonly on review paths that actually need it)Workflow behavior (security + edge cases)
Trusted trigger gate
/design-reviewcomments from maintainers (OWNER/MEMBER/COLLABORATOR) are accepted.workflow_dispatchis supported for manual re-runs on a specific PR number.External/fork PR handling
head.shaSKIPPEDand exitALLOW_EXTERNAL_PR_REVIEW=truefor that runDiff filtering
Design-relevant files are included when:
src/,src/css/,src/theme/,src/components/,docs/,versioned_docs/,static/,design-agent/tailwind.config.*,docusaurus.config.*.css,.scss,.module.css,.ts,.tsx,.js,.jsx,.md,.mdx,.svg,.png,.jpg,.jpeg,.webp,.gifdesign-agent/DOCS_DESIGN_GUIDELINES.mdMissing patches / binary diffs
patch: nullfor relevant files:[NO_PATCH_AVAILABLE]note in the internal diff textMANUAL_REVIEW_REQUIREDand does not call AnthropicLLM invocation hardening
CHANGES_REQUESTED)|Comment behavior (no spam)
.../blob/{pr.head.sha}/{path}How to use
/design-reviewManual run:
workflow_dispatchand providepr-number.Required secrets / env
GitHub Actions secrets:
ANTHROPIC_API_KEYDESIGN_COMMONS_TOKEN(must have read access tokeploy/landing-page)Workflow env (set in workflow):
GITHUB_TOKEN: ${{ github.token }}COMMON_GUIDELINES_REPO(defaultkeploy/landing-page)COMMON_GUIDELINES_PATH(defaultdesign-agent/COMMON_DESIGN_GUIDELINES.md)COMMON_GUIDELINES_REF(defaultmain)PR_NUMBER,PR_HEAD_SHA,PR_HEAD_REPO_FULL_NAME,IS_EXTERNAL_PR,GITHUB_REPOSITORYOptional:
ALLOW_EXTERNAL_PR_REVIEW=true(only when explicitly allowing external PR reviews)Validation performed
python3 -m py_compile design-agent/scripts/design_review.pyImplementation sources / references
Repo-internal sources used to generate docs-specific policy
package.jsondocusaurus.config.jstailwind.config.jssrc/css/custom.csssrc/theme/**(notablysrc/theme/DocItem/*,src/theme/Heading/*)src/components/**(Tailwind-first components)External/public references that informed the implementation choices
(Links are provided for reviewer context; they are not required at runtime.)
issue_commentevent payload fields (includingauthor_association):GET /repos/{owner}/{repo}/pulls/{pull_number}GET /repos/{owner}/{repo}/pulls/{pull_number}/filesGET /repos/{owner}/{repo}/contents/{path}[rest](https://docs.github.com/rest)contentblocks):