@olegkoval/agent-skills 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +3 -2
- package/.cursor-plugin/index.json +5 -0
- package/.grok-plugin/index.json +5 -0
- package/.kiro/steering/qodoloop.md +127 -0
- package/.windsurf/rules/qodoloop.md +126 -0
- package/README.md +4 -3
- package/catalog/skills.json +24 -0
- package/package.json +1 -1
- package/packages/software-development/qodoloop/SKILL.md +134 -0
- package/packages/software-development/qodoloop/adapters/claude/plugin.json +5 -0
- package/packages/software-development/qodoloop/adapters/claude/skills/qodoloop/SKILL.md +135 -0
- package/packages/software-development/qodoloop/adapters/codex/README.md +20 -0
- package/packages/software-development/qodoloop/adapters/cursor/plugin.json +6 -0
- package/packages/software-development/qodoloop/adapters/cursor/skills/qodoloop/SKILL.md +136 -0
- package/packages/software-development/qodoloop/adapters/grok/plugin.json +6 -0
- package/packages/software-development/qodoloop/adapters/grok/skills/qodoloop/SKILL.md +135 -0
- package/packages/software-development/qodoloop/adapters/kiro/steering/qodoloop.md +127 -0
- package/packages/software-development/qodoloop/adapters/windsurf/rules/qodoloop.md +126 -0
- package/packages/software-development/qodoloop/references/graphql-queries.md +151 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# GraphQL queries reference
|
|
2
|
+
|
|
3
|
+
Field names verified by introspection against GitHub's live GraphQL schema
|
|
4
|
+
(`AddPullRequestReviewThreadReplyInput`) and against a real Qodo install's
|
|
5
|
+
comment output — not guessed.
|
|
6
|
+
|
|
7
|
+
**The bot's login string is spelled differently in REST vs GraphQL.** REST
|
|
8
|
+
(`.user.login` on `issues/.../comments`) returns `qodo-code-review[bot]`.
|
|
9
|
+
GraphQL (`author.login` on `reviewThreads`) returns `qodo-code-review` — no
|
|
10
|
+
`[bot]` suffix — confirmed live against a real PR with real Qodo inline
|
|
11
|
+
threads. Using the REST spelling in a GraphQL filter silently matches
|
|
12
|
+
nothing, which reads as "no findings" instead of "wrong filter" — exactly the
|
|
13
|
+
kind of bug that has no crash and no error to notice. Use `[bot]` only in
|
|
14
|
+
REST-based jq filters (`.user.login`); use the bare name everywhere you're
|
|
15
|
+
filtering a GraphQL `author.login`.
|
|
16
|
+
|
|
17
|
+
## Fetch unresolved Qodo threads (paginated)
|
|
18
|
+
|
|
19
|
+
```graphql
|
|
20
|
+
query($cursor: String) {
|
|
21
|
+
repository(owner: "OWNER", name: "REPO") {
|
|
22
|
+
pullRequest(number: PR_NUMBER) {
|
|
23
|
+
reviewThreads(first: 100, after: $cursor) {
|
|
24
|
+
pageInfo { hasNextPage endCursor }
|
|
25
|
+
nodes {
|
|
26
|
+
id
|
|
27
|
+
isResolved
|
|
28
|
+
comments(first: 1) {
|
|
29
|
+
nodes { body path line author { login } }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Filter client-side to `qodo-code-review` (GraphQL spelling — see the note
|
|
39
|
+
above) and `isResolved == false` — the author isn't filterable server-side in
|
|
40
|
+
this shape. **Follow `pageInfo.hasNextPage`/`endCursor` until it's exhausted**;
|
|
41
|
+
stopping after the first page silently drops every thread past the 100th on a
|
|
42
|
+
PR with a lot of findings:
|
|
43
|
+
|
|
44
|
+
A page fetch can occasionally come back malformed (a transient API hiccup,
|
|
45
|
+
not anything specific to this query — reproduced live, then failed to
|
|
46
|
+
reproduce on an identical immediate retry). Retry once per page before
|
|
47
|
+
giving up rather than letting the whole loop crash on it:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
CURSOR=null
|
|
51
|
+
ALL_THREADS='[]'
|
|
52
|
+
while :; do
|
|
53
|
+
for attempt in 1 2; do
|
|
54
|
+
PAGE=$(gh api graphql -f query='
|
|
55
|
+
query($cursor: String) {
|
|
56
|
+
repository(owner: "OWNER", name: "REPO") {
|
|
57
|
+
pullRequest(number: PR_NUMBER) {
|
|
58
|
+
reviewThreads(first: 100, after: $cursor) {
|
|
59
|
+
pageInfo { hasNextPage endCursor }
|
|
60
|
+
nodes {
|
|
61
|
+
id
|
|
62
|
+
isResolved
|
|
63
|
+
comments(first: 1) { nodes { body path line author { login } } }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}' -f cursor="$CURSOR")
|
|
69
|
+
jq -e . >/dev/null 2>&1 <<< "$PAGE" && break
|
|
70
|
+
[ "$attempt" = "2" ] && { echo "page fetch failed twice, aborting" >&2; exit 1; }
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
ALL_THREADS=$(jq -c --argjson acc "$ALL_THREADS" \
|
|
74
|
+
'$acc + .data.repository.pullRequest.reviewThreads.nodes' <<< "$PAGE")
|
|
75
|
+
|
|
76
|
+
HAS_NEXT=$(jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage' <<< "$PAGE")
|
|
77
|
+
[ "$HAS_NEXT" = "true" ] || break
|
|
78
|
+
CURSOR=$(jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor' <<< "$PAGE")
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
echo "$ALL_THREADS" | jq \
|
|
82
|
+
'.[] | select(.comments.nodes[0].author.login == "qodo-code-review") | select(.isResolved == false)'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Parsing a thread's finding out of `comments.nodes[0].body`
|
|
86
|
+
|
|
87
|
+
The body is markdown with embedded HTML. Extract:
|
|
88
|
+
- **Title + severity**: first line has a badge image; `alt="Remediation recommended"` = actionable, `alt="Informational"` = optional. The finding title/tags follow on the next line (e.g. `3\. pickclaimroaster branch untested <code>📘 Rule violation</code> ...`).
|
|
89
|
+
- **Agent Prompt**: the fenced ```` ```...``` ```` block under a `<summary>` reading either `Agent Prompt` or `Agent prompt` (Qodo's casing differs between the inline-comment surface and the rollup issue-comment surface — match case-insensitively). This block is the whole fix spec: issue description, context, fix focus files/lines, and often a suggested fix. Use it verbatim as the task.
|
|
90
|
+
|
|
91
|
+
If a thread somehow has no Agent Prompt block (seen only on the rollup's
|
|
92
|
+
lower-severity "Optional" entries in some cases), fall back to the finding's
|
|
93
|
+
plain-text description above the badge.
|
|
94
|
+
|
|
95
|
+
## Reply to a thread
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
gh api graphql -f query='
|
|
99
|
+
mutation($threadId: ID!, $body: String!) {
|
|
100
|
+
addPullRequestReviewThreadReply(input: {pullRequestReviewThreadId: $threadId, body: $body}) {
|
|
101
|
+
comment { id }
|
|
102
|
+
}
|
|
103
|
+
}' -f threadId="$THREAD_ID" -f body="$REPLY_TEXT"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Pass the thread id and reply text as GraphQL **variables** (`-f`), never
|
|
107
|
+
interpolated straight into the query string. A reply containing a quote,
|
|
108
|
+
backtick, or embedded newline breaks — or, worse, injects into — a
|
|
109
|
+
hand-built query string; `gh api graphql -f` handles the escaping correctly
|
|
110
|
+
when the value travels as a variable instead.
|
|
111
|
+
|
|
112
|
+
`pullRequestReviewThreadId` and `body` are the only required input fields
|
|
113
|
+
(`pullRequestReviewId` and `clientMutationId` are optional — omit them).
|
|
114
|
+
|
|
115
|
+
## Resolve a thread (batch)
|
|
116
|
+
|
|
117
|
+
```graphql
|
|
118
|
+
mutation {
|
|
119
|
+
t1: resolveReviewThread(input: {threadId: "ID1"}) { thread { isResolved } }
|
|
120
|
+
t2: resolveReviewThread(input: {threadId: "ID2"}) { thread { isResolved } }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Only resolve a thread whose fix is already pushed and confirmed durable on
|
|
125
|
+
the branch (SKILL.md §2E-F) — resolving first and pushing second means a
|
|
126
|
+
failed push leaves GitHub showing the finding as handled when it isn't. Never
|
|
127
|
+
resolve a blocked/skipped finding at all; reply to it and leave it open.
|
|
128
|
+
|
|
129
|
+
## Fetch the rollup issue comment (context only, not the source of truth)
|
|
130
|
+
|
|
131
|
+
Useful for the human-readable summary counts (bugs/rule-violations) in your
|
|
132
|
+
final report, or as a fallback if `reviewThreads` ever comes back empty for a
|
|
133
|
+
PR that clearly has a completed review. Select the latest by `created_at`.
|
|
134
|
+
Whether Qodo edits this comment in place across passes or posts a new one
|
|
135
|
+
each time is **unconfirmed** — every PR checked had exactly one, untouched
|
|
136
|
+
since creation, which doesn't distinguish the two. Sort by `created_at` and
|
|
137
|
+
take the last one either way; it's correct under both behaviors:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gh api --paginate "repos/{owner}/{repo}/issues/<PR_NUMBER>/comments?per_page=100" \
|
|
141
|
+
| jq -s 'add
|
|
142
|
+
| map(select(.user.login == "qodo-code-review[bot]"))
|
|
143
|
+
| map(select(.body | startswith("<h3>Code Review by Qodo</h3>")))
|
|
144
|
+
| sort_by(.created_at)
|
|
145
|
+
| last'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
A rate-limit/paused comment reads `<h3>Qodo is busy working</h3>` while
|
|
149
|
+
in-flight, or contains "Qodo reviews are paused" / "review limit" when
|
|
150
|
+
terminally blocked — check for that text before assuming a missing review
|
|
151
|
+
comment just means "still running".
|