com um clique
com um clique
Create and update dashboard and workflow documentation
Create and update Dynatrace dashboards for DSOA telemetry
Create and update Dynatrace workflows for DSOA automation
Create and update DSOA plugins — full development lifecycle from planning through validation
AI-guided QA walkthrough for DSOA releases. Automates version detection, deployment commands, notebook deployment, and interactive test walkthrough. Use when a QA engineer needs to execute the DSOA release test suite.
Create and update Snowflake synthetic test setups for DSOA telemetry validation
| name | pr-reviewer |
| description | Review a pull request and process review comments left by others |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"developers"} |
Use this skill when asked to:
| Input | Required | Description |
|---|---|---|
| PR number | yes | The GitHub pull request number (e.g. 80) |
| Product improvement notes | no | Feature/improvement brief that motivated this PR |
| Implementation plan | no | Ordered task list describing what the PR is supposed to do |
If the product improvement or implementation plan are not supplied, infer intent from the PR title, body, and diff — but note the gap when reporting findings.
Run all reads in parallel where possible to minimise latency.
gh repo view --json nameWithOwner
# → { "nameWithOwner": "dynatrace-oss/dynatrace-snowflake-observability-agent" }
Store OWNER and REPO for all subsequent calls.
gh pr view <PR#> --json number,title,body,baseRefName,headRefName,state,author,labels,milestone
gh pr diff <PR#>
The diff is the primary artefact for a review. Read it fully before drawing any conclusions.
Use the GitHub GraphQL API to get rich thread data including file paths, line
numbers, diff hunks, and resolution status. Request enough nodes to cover all
threads — increase the first: value if the PR is large.
gh api graphql -f query='
{
repository(owner: "<OWNER>", name: "<REPO>") {
pullRequest(number: <PR#>) {
title
body
reviewThreads(first: 50) {
nodes {
id
isResolved
isOutdated
path
line
originalLine
diffHunk
comments(first: 10) {
nodes {
databaseId
author { login }
body
createdAt
updatedAt
minimizedReason
}
}
}
}
reviews(first: 20) {
nodes {
author { login }
state
body
submittedAt
}
}
}
}
}'
Pipe through python3 -m json.tool for readable output. Store the result — it
is the source of truth for all comment-processing decisions.
For every file mentioned in review threads or the diff, read the surrounding
context using the Read tool (not cat). For large files, use offset + limit
or the Grep tool to jump to the relevant region.
# Example: read lines 220-260 of a file referenced in a thread
# Use the Read tool with offset=220, limit=40
Do not guess at context. Read the actual file before forming an opinion.
For every thread from the GraphQL result, assign:
| Field | Values |
|---|---|
| Status | open / resolved / outdated |
| Severity | critical / important / minor / nit |
| Category | correctness / style / docs / tests / perf / security / architecture |
| Action | fix / address-in-comment / defer / disagree / already-done |
Severity guide:
critical — bug, data loss, security issue, broken contract, test that does not catch what it claims to catch.important — meaningful quality regression, misleading naming, incomplete coverage.minor — improvement that is clearly better but not blocking.nit — style, spelling, personal preference with no functional impact.If an implementation plan was provided, verify:
Beyond the existing comments, check for:
make lint, pylint 10.00/10, black, flake8, sqlfluff).docs/PLUGIN_DEVELOPMENT.md for the plugin
test pattern).instruments-def.yml updates for new plugins or metrics.CHANGELOG.md / DEVLOG.md updates where required.Before concluding that something is broken or missing, consult the actual source files. Do not flag issues based on the diff alone when the answer might be in an unchanged file.
Produce a structured plan in this format:
## PR #<N> — Improvement Plan
### Summary
<One paragraph: overall assessment, whether the PR is ready to merge, and the
main concerns.>
### Action Items
| # | Thread / Finding | File | Line | Severity | Category | Action | Notes |
|---|---|---|---|---|---|---|---|
| 1 | <thread id or "own"> | `path/to/file.py` | 123 | critical | correctness | fix | <what to do> |
| 2 | ... | | | | | | |
### Out-of-scope changes detected
<List any diff hunks that appear unrelated to the PR goal, or "None".>
### Deferred items
<Items that are valid but should be handled in a separate PR.>
Consult the human before acting on any item that would:
Present the plan to the human and wait for approval before moving to Phase 4.
Work through the approved action items one at a time:
in_progress in the TodoWrite tool.Read tool.Edit tool.make lint and .venv/bin/pytest after each change — do not batch.completed only after tests and lint are green.make lint # full lint suite
.venv/bin/pytest # full test suite
.venv/bin/pytest test/plugins/test_<X>.py -v # single plugin
If a test fails, diagnose the root cause and fix it. Never "fix" a test by adjusting expected values to match wrong output — fix the code.
After completing all fixes, post a structured review using the GitHub CLI or the GitHub MCP tool.
# Approve
gh pr review <PR#> --approve --body "<review body>"
# Request changes
gh pr review <PR#> --request-changes --body "<review body>"
# Comment only
gh pr review <PR#> --comment --body "<review body>"
Use github_create_pull_request_review with comments array for line-level
annotations. Each comment needs path, line, and body.
## Review — PR #<N>: <title>
### Overall Assessment
<APPROVE / REQUEST_CHANGES / COMMENT> — <one sentence why>
### Critical Issues
<numbered list, or "None">
### Important Issues
<numbered list, or "None">
### Minor / Nit
<numbered list, or "None">
### Positive Observations
<what is done well — be specific>
When processing comments left by other reviewers (human or bot):
open thread: decide fix, address-in-comment, or defer.resolved threads: verify the fix is actually present in the diff —
do not trust the resolved flag blindly.copilot-pull-request-reviewer): evaluate on merit,
not authority. Bots can be wrong.databaseId from the GraphQL result:# Reply to a specific review thread (requires the thread's first comment databaseId)
gh api repos/<OWNER>/<REPO>/pulls/<PR#>/comments/<comment-id>/replies \
-f body="<your reply>"
Reply template:
"Fixed in commit <sha>. <one sentence describing what changed and why.>""Acknowledged. Deferred to a follow-up — <brief rationale>.""Disagree: <technical reasoning>. Leaving as-is.""This is already handled in <file>:<line> — <brief explanation>."Run all replies in parallel (one gh api call per thread) — do not wait between replies.
gh api graphql -f query='
{
repository(owner: "<OWNER>", name: "<REPO>") {
pullRequest(number: <PR#>) {
reviewThreads(first: 50) {
nodes {
isResolved
path
line
comments(first: 5) {
nodes { author { login } body }
}
}
}
}
}
}' | python3 -c "
import json, sys
data = json.load(sys.stdin)
threads = data['data']['repository']['pullRequest']['reviewThreads']['nodes']
open_threads = [t for t in threads if not t['isResolved']]
print(f'{len(open_threads)} open thread(s)')
for t in open_threads:
print(f\" {t['path']}:{t['line']} — {t['comments']['nodes'][0]['body'][:80]}\")
"
gh pr view <PR#> --json files --jq '.files[].path'
Use the Read tool with offset and limit parameters — do not use sed -n
or head/tail.
-p flag) to regenerate fixtures from real output..venv/bin/python / .venv/bin/pytest. Never system Python.