Skip to content

feat: implement design agent for ui reviews#824

Open
amaan-bhati wants to merge 14 commits intomainfrom
design-agent
Open

feat: implement design agent for ui reviews#824
amaan-bhati wants to merge 14 commits intomainfrom
design-agent

Conversation

@amaan-bhati
Copy link
Copy Markdown
Member

@amaan-bhati amaan-bhati commented Apr 8, 2026

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:

  • Adds a Python-based runtime agent (design-agent/scripts/design_review.py) + a GitHub Actions workflow (.github/workflows/design-review.yml).
  • Merges private/common guidelines (fetched at runtime from keploy/landing-page) with docs-repo-specific guidelines (generated from this repo’s actual styling + theme code).
  • Strong safety posture for external/fork PRs (default skip unless explicitly allowed).
  • Robust diff filtering + edge case handling for missing patches / binary files.
  • Hard output contract + strict verdict parsing (fails fast if malformed).

What changed

New agent runtime

  • design-agent/scripts/design_review.py
    • Resolves PR context (PR_NUMBER, plus head.sha / head.repo.full_name).
    • Fetches PR file list and patches via GitHub REST API (pulls/{pull_number}/files).
    • Filters diffs to docs UI/design surfaces (paths + extensions) and explicitly excludes design-agent/DOCS_DESIGN_GUIDELINES.md from diff payload (prevents circular self-review).
    • If no design-relevant diff remains: exits quietly (no noisy comment).
    • If only “no patch” files exist (patch == null / empty): posts MANUAL_REVIEW_REQUIRED and skips Anthropic.
    • If external/fork PR and ALLOW_EXTERNAL_PR_REVIEW not true: posts SKIPPED and returns.
    • Otherwise loads guidelines (private common + local docs-specific), invokes Anthropic, validates strict template, parses verdict, and upserts a single PR comment using a hidden marker:
      • <!-- design-agent-review-comment -->
    • Footer links are pinned to pr.head.sha (blob links for exact reviewed versions).

New workflow

  • .github/workflows/design-review.yml
    • Triggers: pull_request, issue_comment, workflow_dispatch.
    • Permissions (explicit, minimal for required behavior):
      • pull-requests: write
      • issues: write
      • contents: read
    • Uses GITHUB_TOKEN: ${{ github.token }} (not secrets.GITHUB_TOKEN).
    • Trusted comment trigger only:
      • comment body must equal /design-review
      • actor association must be OWNER / MEMBER / COLLABORATOR
    • Resolves PR number first (supports workflow_dispatch input github.event.inputs['pr-number']).
    • Resolves PR metadata (head.sha, head.repo.full_name, base repo, default branch) via GitHub API.
    • Safe checkout:
      • internal PR: checkout pr.head.sha
      • external/fork PR: checkout default branch (prevents executing untrusted fork code from checkout)
    • Runs the Python agent with required env.

Repo-specific guidelines (generated from this repo)

  • design-agent/DOCS_DESIGN_GUIDELINES.md
    • Produced by reading current repo implementation details, including:
      • package.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/** and src/components/** (patterns used in actual code)
    • Intentionally does not copy the private/common policy text.

Dependencies

  • design-agent/requirements.txt
    • Pinned versions for deterministic installs:
      • anthropic==0.40.0
      • PyGithub==2.1.1

Documentation

  • design-agent/README.md
    • Architecture (private + local guidelines merge)
    • Security model (trusted trigger, fork handling, secret usage)
    • How to run + troubleshooting

Why this approach

Why a Python script (instead of JS-only)

The agent is implemented as a single Python entrypoint for reliability + security hardening:

  • Centralizes all “critical-path” logic (PR metadata resolution, diff filtering, guideline loading, output validation, comment upsert) in one audited runtime.
  • Strong control over HTTP requests + payload handling (base64 decode of the contents API response, pagination safety limits, comment size safety truncation).
  • Enables strict template validation + verdict parsing in a small, deterministic runtime with minimal moving parts.
  • Keeps the execution model explicit and constrained inside the workflow (easy to reason about when secrets are required vs not).

Note: PyGithub is 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:

  • avoids duplicating private policy text in this repo
  • ensures the agent always reviews against the current shared policy version (COMMON_GUIDELINES_REF, default main)
  • provides a controlled access boundary (requires DESIGN_COMMONS_TOKEN only on review paths that actually need it)

Workflow behavior (security + edge cases)

Trusted trigger gate

  • Only /design-review comments from maintainers (OWNER/MEMBER/COLLABORATOR) are accepted.
  • workflow_dispatch is supported for manual re-runs on a specific PR number.

External/fork PR handling

  • Checkout behavior is safe by default:
    • internal PR: checkout head.sha
    • external PR: checkout base repo default branch
  • Script behavior for external PRs:
    • default: post SKIPPED and exit
    • override: set ALLOW_EXTERNAL_PR_REVIEW=true for that run

Diff filtering

Design-relevant files are included when:

  • path is in: src/, src/css/, src/theme/, src/components/, docs/, versioned_docs/, static/, design-agent/
  • OR is a root config: tailwind.config.*, docusaurus.config.*
  • AND extension is one of:
    • .css, .scss, .module.css, .ts, .tsx, .js, .jsx, .md, .mdx, .svg, .png, .jpg, .jpeg, .webp, .gif
  • Excluded explicitly:
    • design-agent/DOCS_DESIGN_GUIDELINES.md

Missing patches / binary diffs

  • If GitHub returns patch: null for relevant files:
    • the agent records a [NO_PATCH_AVAILABLE] note in the internal diff text
    • if all relevant files are no-patch: posts MANUAL_REVIEW_REQUIRED and does not call Anthropic

LLM invocation hardening

  • Retries empty Anthropic output once (2 attempts total).
  • Concatenates all returned content blocks (not just the first).
  • Enforces strict output sections and a single-token verdict.
  • Verdict parsing rules:
    • preserves underscores (tokens like CHANGES_REQUESTED)
    • ignores lines containing |
    • accepts only exactly one known verdict token line
  • If review text exists but verdict can’t be parsed: job fails (prevents ambiguous automation).

Comment behavior (no spam)

  • Uses upsert via hidden marker:
    • edits existing comment if present, otherwise creates one
  • Footer links pin review to exact commit:
    • .../blob/{pr.head.sha}/{path}

How to use

  1. Open a PR.
  2. Comment exactly:
    • /design-review
  3. The agent posts/updates a single PR comment with verdict + details.

Manual run:

  • Use workflow_dispatch and provide pr-number.

Required secrets / env

GitHub Actions secrets:

  • ANTHROPIC_API_KEY
  • DESIGN_COMMONS_TOKEN (must have read access to keploy/landing-page)

Workflow env (set in workflow):

  • GITHUB_TOKEN: ${{ github.token }}
  • COMMON_GUIDELINES_REPO (default keploy/landing-page)
  • COMMON_GUIDELINES_PATH (default design-agent/COMMON_DESIGN_GUIDELINES.md)
  • COMMON_GUIDELINES_REF (default main)
  • PR_NUMBER, PR_HEAD_SHA, PR_HEAD_REPO_FULL_NAME, IS_EXTERNAL_PR, GITHUB_REPOSITORY

Optional:

  • ALLOW_EXTERNAL_PR_REVIEW=true (only when explicitly allowing external PR reviews)

Validation performed

  • python3 -m py_compile design-agent/scripts/design_review.py

Implementation sources / references

Repo-internal sources used to generate docs-specific policy

  • package.json
  • docusaurus.config.js
  • tailwind.config.js
  • src/css/custom.css
  • src/theme/** (notably src/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.)

  • GitHub Actions contexts + permissions:
  • issue_comment event payload fields (including author_association):
  • GitHub REST API:
    • PR metadata: GET /repos/{owner}/{repo}/pulls/{pull_number}
    • PR files: GET /repos/{owner}/{repo}/pulls/{pull_number}/files
    • Repo contents API (private common guidelines): GET /repos/{owner}/{repo}/contents/{path}
    • Reference: [rest](https://docs.github.com/rest)
  • Anthropic Python SDK (message format, content blocks):

Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Copilot AI review requested due to automatic review settings April 8, 2026 18:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +235 to +245
| 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.

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
| Context | Value |
|---------|-------|
| Content reading area | `max-width: 860px` |
| Sidebar width (default) | `260px` |
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
| Sidebar width (default) | `260px` |
| Sidebar width (default) | `275px` |

Copilot uses AI. Check for mistakes.
| 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 |
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
| 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 |

Copilot uses AI. Check for mistakes.
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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

run: |
cd .github/scripts
npm init -y --quiet
npm install @anthropic-ai/sdk@latest --save --quiet
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
npm install @anthropic-ai/sdk@latest --save --quiet
npm install @anthropic-ai/sdk@0.32.1 --save-exact --quiet

Copilot uses AI. Check for mistakes.

on:
pull_request:
types: [opened, synchronize, reopened]
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested 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"

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +22
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);
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +67
// 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);

Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +22
const IGNORED_PATHS = [
"node_modules/",
"build/",
".docusaurus/",
"package-lock.json",
"yarn.lock",
"pnpm-lock.yaml",
];
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/.

Copilot uses AI. Check for mistakes.
.get(options, (res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => resolve(data));
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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);
});

Copilot uses AI. Check for mistakes.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
@amaan-bhati amaan-bhati requested a review from Copilot April 10, 2026 04:52
@github-actions
Copy link
Copy Markdown

Keploy Design Review

✅ No design-relevant files changed in this diff. Nothing to review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +3 to +15
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- "**.css"
- "**.scss"
- "**.mdx"
- "**.md"
- "**.tsx"
- "**.jsx"
- "**.js"
- "**.ts"

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +22
// 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");
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +95
const message = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 4096,
messages: [
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +78
console.error("ERROR: ANTHROPIC_API_KEY environment variable is not set.");
process.exit(1);
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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;

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +80
/**
* 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);
});

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
/**
* 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);

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +85
const botComments = comments.filter(
(c) =>
c.user.type === "Bot" &&
c.body.includes("Keploy Design Review")
);
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +540 to +569
### 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
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Signed-off-by: amaan-bhati <amaanbhati49@gmail.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@amaan-bhati amaan-bhati changed the title feat: set the design guideline agent guidelines for ui reviews feat: implement design agent for ui reviews Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants