GlaDOS-agent/AGENTS.md
Overtorment 13850607a4 init
2026-06-20 10:53:35 +01:00

5.1 KiB

cursor-glados — agent guide

GLaDOS polls GitHub for review-request notifications, clones each PR locally, runs a Cursor SDK agent review, and posts the result back to GitHub (summary + inline comments, approve or request changes).

TypeScript, ESM ("type": "module"), Node ≥ 22.13. Run scripts with tsx.

Commands

export GLADOS_TOKEN='ghp_...'      # GitHub PAT: notifications + repo + pull_requests
export CURSOR_API_KEY='cursor_...'

npm run notifications              # poll review_requested notifications, review each PR
npm run notifications -- --all     # include read notifications
npm run smoke                      # local Cursor SDK smoke test (cwd = this repo)
npm run typecheck

@connectrpc/connect-node is required at runtime by @cursor/sdk but is not bundled — keep it in package.json.

Layout

Only src/cli/ contains runnable entrypoints. Everything else is library code imported by CLI or other modules.

src/
  cli/
    notifications.ts    # entrypoint: list notifications → review each review_requested
    smoke.ts            # entrypoint: one-shot local Agent.prompt smoke test

  types.ts              # NotificationThread, PullRequestRef

  git/
    workspace.ts        # clone repo to temp dir, fetch + checkout PR branch

  github/
    notifications.ts    # listNotifications() — paginated /notifications API
    pr.ts               # parsePullRequest(), subjectUrlToWebUrl()
    diff.ts             # getCommentableLines() — RIGHT-side lines that accept comments
    reviews.ts          # postGithubReview() — validate vs diff, then createReview

  review/
    process.ts          # processReviewRequest() — orchestrates full review flow
    agent.ts            # runAgentReview() — Cursor SDK Agent.prompt on local cwd
    payload.ts          # prompt, JSON parse, GitHub review formatting, personality hook

Review flow

cli/notifications.ts
  → github/notifications.listNotifications()
  → filter reason === "review_requested"
  → review/process.processReviewRequest()  (per notification)
       → github/pr.parsePullRequest()
       → github/pr.isReviewRequestedForUser()  # skip if not on pending reviewer list
       → git/workspace.preparePrWorkspace()   # /tmp/glados-*/<repo>
       → review/agent.runAgentReview()        # local Agent.prompt
       → review/payload.buildGithubReview()   # APPROVE vs REQUEST_CHANGES
       → github/reviews.postGithubReview()
       → rm temp workspace

Duplicate protection: before cloning, isReviewRequestedForUser() calls GET .../pulls/{n}/requested_reviewers. GitHub only lists users with a pending review request — once you submit a review you drop off; if someone re-requests you, you're back. Review only when the GLADOS user is on that list.

Tests: GLaDOS does not run the test suite or install deps to execute tests. The PR's CI runs tests; the agent reviews test code by reading files only. This is enforced in buildReviewPrompt().

Approve vs request changes: critical or high findings → REQUEST_CHANGES; otherwise APPROVE.

Inline comments: findings with path + line become review comments (side: RIGHT). The agent reviews the whole repo, so it can cite lines outside the diff — but GitHub only accepts RIGHT-side comments on lines present in the PR diff, and one bad anchor 422s the entire inline batch. So before posting, github/diff.tsgetCommentableLines() parses the PR diff hunks and reviews.ts filters comments against it: anchorable lines post inline, the rest are demoted into the review body (appendCommentsToBody). Findings without path/line go in the body too. A body-only 422 fallback remains as a last resort.

Key extension points

What Where
Reviewer instructions / JSON schema review/payload.tsbuildReviewPrompt()
Severity levels (single source of truth) review/payload.tsSEVERITIES const + Severity type
GLaDOS voice before posting review/payload.tsapplyPersonality()
Clone/checkout behavior git/workspace.ts
GitHub API (notifications, PR parse, post review) github/
Orchestration only — no business logic review/process.ts

Tune the review prompt and personality independently: prompt asks for structured JSON; applyPersonality() rewrites text at post time.

Conventions

  • ESM imports use .js extensions in TypeScript source (import x from "./foo.js").
  • New runnable scripts go in src/cli/ only. Wire them in package.json scripts.
  • New library code goes in the matching domain folder (github/, git/, review/), not a generic utils/.
  • Keep modules small: agent.ts = SDK only, payload.ts = pure data/prompt/formatting, process.ts = wiring.
  • Minimize scope on changes — match existing style, no over-abstraction.

Environment

Variable Used for
GLADOS_TOKEN GitHub API (notifications, clone auth, post reviews)
CURSOR_API_KEY Cursor SDK local agent runs

GLADOS_TOKEN needs access to arbitrary repos that send review requests (repo scope or equivalent fine-grained permissions).