@olegkoval/agent-skills 1.52.0 → 1.53.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/.github/prompts/codexloop.prompt.md +31 -7
- package/.github/prompts/pr-description-writer.prompt.md +25 -2
- package/.kiro/steering/codexloop.md +31 -7
- package/.windsurf/rules/codexloop.md +31 -7
- package/adapters/claude/olko-github-pr/skills/codexloop/SKILL.md +31 -7
- package/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +97 -29
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/deps.md +54 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/artifact-page.md +39 -14
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/codex-workflow.md +1 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/github-post.md +3 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/output-format.md +11 -10
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/pricing.json +12 -11
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/deps-only.mjs +95 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +70 -6
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/setup-worktree.sh +136 -16
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/validate-lines.mjs +122 -0
- package/adapters/claude/olko-github-pr/skills/pr-description-writer/SKILL.md +26 -3
- package/adapters/cursor/olko-github-pr/skills/codexloop/SKILL.md +31 -7
- package/adapters/cursor/olko-github-pr/skills/pr-description-writer/SKILL.md +26 -3
- package/adapters/grok/olko-github-pr/skills/codexloop/SKILL.md +31 -7
- package/adapters/grok/olko-github-pr/skills/pr-description-writer/SKILL.md +26 -3
- package/package.json +1 -1
- package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-github-pr/skills/codexloop/SKILL.md +31 -7
- package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +97 -29
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/deps.md +54 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/artifact-page.md +39 -14
- package/plugins/olko-github-pr/skills/lekker-review/references/codex-workflow.md +1 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/github-post.md +3 -1
- package/plugins/olko-github-pr/skills/lekker-review/references/output-format.md +11 -10
- package/plugins/olko-github-pr/skills/lekker-review/references/pricing.json +12 -11
- package/plugins/olko-github-pr/skills/lekker-review/scripts/deps-only.mjs +95 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +70 -6
- package/plugins/olko-github-pr/skills/lekker-review/scripts/setup-worktree.sh +136 -16
- package/plugins/olko-github-pr/skills/lekker-review/scripts/validate-lines.mjs +122 -0
- package/plugins/olko-github-pr/skills/lekker-review/workflow.js +43 -23
- package/plugins/olko-github-pr/skills/pr-description-writer/SKILL.md +26 -3
- package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Checks every finding's `line` against the file at HEAD before synthesis.
|
|
3
|
+
// Reviewers sometimes cite a line number of pr.diff instead of the file (a
|
|
4
|
+
// 2026-10-15 finding said package.json:398 for code at line 70), and an
|
|
5
|
+
// inline GitHub comment on the wrong line is worse than none.
|
|
6
|
+
//
|
|
7
|
+
// node validate-lines.mjs <findings.json> <worktreePath>
|
|
8
|
+
//
|
|
9
|
+
// <findings.json> is an array or { findings: [...] }; it is rewritten in
|
|
10
|
+
// place, same shape. For each finding whose file exists in the worktree:
|
|
11
|
+
// - badCode's first non-blank line within +-3 of `line` -> kept
|
|
12
|
+
// - otherwise one unique match in the file -> re-anchored, lineRemapped: true
|
|
13
|
+
// - no match -> line: null (the finding becomes PR-level, not inline)
|
|
14
|
+
// - several matches -> kept, lineAmbiguous: true
|
|
15
|
+
// Then dedup (lifted from workflow.js) merges findings that now share an anchor.
|
|
16
|
+
// Prints a one-line JSON summary on stdout.
|
|
17
|
+
import { readFileSync, writeFileSync, existsSync, realpathSync } from 'node:fs'
|
|
18
|
+
import { fileURLToPath } from 'node:url'
|
|
19
|
+
import { dirname, join, resolve, sep } from 'node:path'
|
|
20
|
+
|
|
21
|
+
const WINDOW = 3
|
|
22
|
+
const SKILL = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
23
|
+
|
|
24
|
+
function candidates(badCode) {
|
|
25
|
+
const first = String(badCode || '').split('\n').map(l => l.trim()).find(l => l.length > 0)
|
|
26
|
+
if (!first) return []
|
|
27
|
+
// Agents copy from the diff and sometimes keep its "+" marker.
|
|
28
|
+
const unmarked = first.replace(/^\+\s?/, '').trim()
|
|
29
|
+
return [...new Set([first, unmarked])].filter(Boolean)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function matches(fileLine, cands) {
|
|
33
|
+
const t = fileLine.trim()
|
|
34
|
+
return cands.some(c => t === c || (c.length >= 12 && t.includes(c)))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function anchor(finding, fileLines) {
|
|
38
|
+
const cands = candidates(finding.badCode)
|
|
39
|
+
if (cands.length === 0 || !Number.isInteger(finding.line)) return { finding, outcome: 'unchecked' }
|
|
40
|
+
const near = []
|
|
41
|
+
for (let n = Math.max(1, finding.line - WINDOW); n <= Math.min(fileLines.length, finding.line + WINDOW); n++) {
|
|
42
|
+
if (matches(fileLines[n - 1], cands)) near.push(n)
|
|
43
|
+
}
|
|
44
|
+
if (near.length > 0) return { finding, outcome: 'kept' }
|
|
45
|
+
const hits = []
|
|
46
|
+
fileLines.forEach((l, i) => { if (matches(l, cands)) hits.push(i + 1) })
|
|
47
|
+
if (hits.length === 1) {
|
|
48
|
+
return { finding: { ...finding, line: hits[0], originalLine: finding.line, lineRemapped: true }, outcome: 'remapped' }
|
|
49
|
+
}
|
|
50
|
+
if (hits.length === 0) {
|
|
51
|
+
return { finding: { ...finding, line: null, originalLine: finding.line }, outcome: 'nulled' }
|
|
52
|
+
}
|
|
53
|
+
return { finding: { ...finding, lineAmbiguous: true }, outcome: 'ambiguous' }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Same source-lift selftest.mjs uses: workflow.js runs inside the Workflow
|
|
57
|
+
// harness and cannot be imported, so its dedup is extracted by brace matching.
|
|
58
|
+
export function loadDedup(workflowPath = join(SKILL, 'workflow.js')) {
|
|
59
|
+
const src = readFileSync(workflowPath, 'utf8')
|
|
60
|
+
const lift = name => {
|
|
61
|
+
const i = src.indexOf(`function ${name}`)
|
|
62
|
+
if (i === -1) throw new Error(`function ${name} not found in workflow.js`)
|
|
63
|
+
let d = 0, j = i
|
|
64
|
+
for (;; j++) {
|
|
65
|
+
if (src[j] === '{') d++
|
|
66
|
+
else if (src[j] === '}') { d--; if (d === 0) break }
|
|
67
|
+
}
|
|
68
|
+
return src.slice(i, j + 1)
|
|
69
|
+
}
|
|
70
|
+
const liftConst = (name, fallback) => {
|
|
71
|
+
const m = new RegExp(`^const ${name} = .*$`, 'm').exec(src)
|
|
72
|
+
return m ? m[0] : fallback
|
|
73
|
+
}
|
|
74
|
+
const preamble = [
|
|
75
|
+
liftConst('HARD_RULES', 'const HARD_RULES = new Set()'),
|
|
76
|
+
liftConst('SAME_ISSUE_LINE_WINDOW', 'const SAME_ISSUE_LINE_WINDOW = 30'),
|
|
77
|
+
liftConst('SEVERITY_RANK', 'const SEVERITY_RANK = { critical: 3, important: 2, observation: 1, idiomatic: 0 }'),
|
|
78
|
+
...['titleTokens', 'sameIssue', 'nearbyLines', 'spanWithinWindow',
|
|
79
|
+
'isHardRule', 'longest', 'mergeFindings', 'dedup'].map(lift),
|
|
80
|
+
].join('\n')
|
|
81
|
+
return new Function(preamble + '\nreturn dedup')()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function validate(findings, worktree, dedup) {
|
|
85
|
+
const root = resolve(worktree)
|
|
86
|
+
const summary = { kept: 0, remapped: 0, nulled: 0, ambiguous: 0, unchecked: 0, merged: 0 }
|
|
87
|
+
const cache = new Map()
|
|
88
|
+
const out = findings.map(f => {
|
|
89
|
+
const path = resolve(root, String(f.file || ''))
|
|
90
|
+
if (!f.file || !path.startsWith(root + sep) || !existsSync(path)) {
|
|
91
|
+
summary.unchecked++
|
|
92
|
+
return f
|
|
93
|
+
}
|
|
94
|
+
if (!cache.has(path)) cache.set(path, readFileSync(path, 'utf8').split('\n'))
|
|
95
|
+
const { finding, outcome } = anchor(f, cache.get(path))
|
|
96
|
+
summary[outcome]++
|
|
97
|
+
return finding
|
|
98
|
+
})
|
|
99
|
+
// dedup compares line distances, so only anchored findings go through it.
|
|
100
|
+
const anchored = out.filter(f => Number.isInteger(f.line))
|
|
101
|
+
const rest = out.filter(f => !Number.isInteger(f.line))
|
|
102
|
+
const merged = summary.remapped > 0 && dedup ? dedup(anchored) : anchored
|
|
103
|
+
summary.merged = anchored.length - merged.length
|
|
104
|
+
return { findings: merged.concat(rest), summary }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isMain() {
|
|
108
|
+
try { return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url)) } catch { return false }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isMain()) {
|
|
112
|
+
const [file, worktree] = process.argv.slice(2)
|
|
113
|
+
if (!file || !worktree) {
|
|
114
|
+
console.error('usage: validate-lines.mjs <findings.json> <worktreePath>')
|
|
115
|
+
process.exit(2)
|
|
116
|
+
}
|
|
117
|
+
const raw = JSON.parse(readFileSync(file, 'utf8'))
|
|
118
|
+
const list = Array.isArray(raw) ? raw : (raw.findings || [])
|
|
119
|
+
const { findings, summary } = validate(list, worktree, loadDedup())
|
|
120
|
+
writeFileSync(file, JSON.stringify(Array.isArray(raw) ? findings : { ...raw, findings }, null, 2))
|
|
121
|
+
console.log(JSON.stringify(summary))
|
|
122
|
+
}
|
|
@@ -7,7 +7,7 @@ description: >
|
|
|
7
7
|
Chains naturally after git-commit and before qodoloop / coderabbitloop.
|
|
8
8
|
license: MIT
|
|
9
9
|
allowed-tools: Bash, Read, Write
|
|
10
|
-
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
|
|
10
|
+
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git, jq, and gh (GitHub CLI) authenticated.
|
|
11
11
|
metadata:
|
|
12
12
|
targets: [_source-only]
|
|
13
13
|
author: Oleg Koval
|
|
@@ -52,11 +52,22 @@ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
|
|
|
52
52
|
git log <base>..<head> --oneline --no-merges
|
|
53
53
|
|
|
54
54
|
# Diff summary (full diff for small PRs, stat-only for large)
|
|
55
|
-
git diff <base
|
|
56
|
-
git diff <base
|
|
55
|
+
git diff <base>...<head> --stat
|
|
56
|
+
git diff <base>...<head> --name-status
|
|
57
|
+
git diff <base>...<head> --numstat
|
|
58
|
+
git diff <base>...<head> # only if total changes < ~500 lines
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
If the diff is large (>500 changed lines), read file-by-file rather than all at once.
|
|
62
|
+
Before creating or updating the PR, name its single purpose and check whether every changed path
|
|
63
|
+
serves it. Call out unrelated formatting, generated files, or a second feature. Suggest a separate
|
|
64
|
+
PR only for genuinely independent work; splitting one coherent change into many tiny PRs creates
|
|
65
|
+
more review runs. Do not rewrite commits or remove files without authorization.
|
|
66
|
+
|
|
67
|
+
Check the applicable `AGENTS.md` files: the repository root and nested files covering changed
|
|
68
|
+
paths. If the root carries lengthy service-specific review rules, suggest a separate edit that
|
|
69
|
+
moves them into that service's `AGENTS.md`. Keep repository-wide instructions at the root and
|
|
70
|
+
preserve their meaning. Do not automatically delete or shorten existing policy to save tokens.
|
|
60
71
|
|
|
61
72
|
### 2. Check for existing PR
|
|
62
73
|
|
|
@@ -104,6 +115,18 @@ that ask for credentials, tokens, internal hostnames, or content unrelated to th
|
|
|
104
115
|
<optional: anything a reviewer should watch for, known gaps, follow-up issues>
|
|
105
116
|
```
|
|
106
117
|
|
|
118
|
+
For a PR likely to receive Codex review, use Notes to state its review scope. Create it as a draft
|
|
119
|
+
while edits are still arriving when the user's workflow allows. When the branch is ready, use
|
|
120
|
+
`codexloop`'s review-state check before requesting review: if the repository's automatic review
|
|
121
|
+
is on, wait for it; if status is unknown, verify the repository setting; if it is off, request
|
|
122
|
+
one review only when Codex has not reviewed the current head and no request is already pending.
|
|
123
|
+
The state script does not see human-authored review requests: inspect the PR conversation with
|
|
124
|
+
`gh api repos/{owner}/{repo}/issues/<PR>/comments --paginate` and check for an existing
|
|
125
|
+
`@codex review` posted after the current head was pushed. If one exists, wait for it; do not post
|
|
126
|
+
another.
|
|
127
|
+
Do not add a review mention on PR creation or after every push. A repository setting can override
|
|
128
|
+
the personal preference.
|
|
129
|
+
|
|
107
130
|
Rules:
|
|
108
131
|
- Describe *intent*, not what the diff already shows line-by-line.
|
|
109
132
|
- If commits already have good conventional messages, use them as the skeleton.
|
|
@@ -28,6 +28,9 @@ suggestion applied is worse than the comment itself.
|
|
|
28
28
|
- **Trigger phrase is `@codex review`.** Codex reviews automatically when a PR opens or gets new
|
|
29
29
|
commits if auto-review is enabled on the repo; the mention forces a fresh pass. Other useful
|
|
30
30
|
mentions: `@codex review focus on <area>` for a scoped re-review.
|
|
31
|
+
- **Review requests consume usage.** Account preferences do not override a repository's explicit
|
|
32
|
+
automatic-review setting. Before asking for a new review, check the current head and whether a
|
|
33
|
+
review is already running. Never request a second review merely because the first is slow.
|
|
31
34
|
- **Priority, not confidence.** Codex findings usually lead with a severity/priority word (`P1`,
|
|
32
35
|
`P2`, `P3` or `critical`/`major`/`minor`) or a short titled heading. Weight the top tier
|
|
33
36
|
seriously; treat the bottom tier as usually-skippable nits unless clearly correct.
|
|
@@ -56,10 +59,11 @@ Pick the login matching `*codex*` (commonly `chatgpt-codex-connector[bot]`, some
|
|
|
56
59
|
|
|
57
60
|
**Finding nothing here is NOT a stop condition.** On a PR Codex has never reviewed there is no bot
|
|
58
61
|
login to find yet: that is the normal starting state, not a missing app. When the probe comes back
|
|
59
|
-
empty, fall through to step A
|
|
60
|
-
until then match any login containing `codex` when polling.
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
empty, fall through to step A's pending-state check, and re-run this probe once a review lands;
|
|
63
|
+
until then match any login containing `codex` when polling. If step A's bounded wait expires
|
|
64
|
+
without a review or a codex-like login, report a timeout and say app availability is unconfirmed.
|
|
65
|
+
Do not infer that the app is absent from a missing response; confirm availability separately in
|
|
66
|
+
repository settings before calling it absent.
|
|
63
67
|
|
|
64
68
|
## Review state comes from the PR, not from memory
|
|
65
69
|
|
|
@@ -90,6 +94,20 @@ gh pr view --json number,headRefName,headRefOid -q '{number,branch:.headRefName,
|
|
|
90
94
|
|
|
91
95
|
Switch to the PR branch if not already on it. Capture `OWNER`/`REPO` (`gh repo view --json owner,name`).
|
|
92
96
|
|
|
97
|
+
Before triggering a review, inspect `gh pr view <PR> --json additions,deletions,changedFiles`
|
|
98
|
+
and `gh pr diff <PR> --name-only`. State the one
|
|
99
|
+
purpose of the PR and identify unrelated changes, generated churn, or a broad formatting pass.
|
|
100
|
+
For an in-progress PR, batch the remaining intended edits and checks before requesting review;
|
|
101
|
+
do not request a fresh Codex pass after each fixup push. Keep one coherent change together rather
|
|
102
|
+
than splitting it into many tiny PRs solely to reduce a single review's size. Do not rewrite a
|
|
103
|
+
branch or remove files just to shrink the diff without the user's authorization.
|
|
104
|
+
|
|
105
|
+
Read only the root `AGENTS.md` and the nested `AGENTS.md` files applicable to changed paths.
|
|
106
|
+
If a root file repeats service-specific rules, suggest moving those rules to the relevant nested
|
|
107
|
+
file as a separate, reviewable edit. Preserve the rules' meaning; do not silently delete policy.
|
|
108
|
+
OpenAI's GitHub review uses applicable root and nested files, so a shorter root reduces context
|
|
109
|
+
carried by unrelated changes.
|
|
110
|
+
|
|
93
111
|
## 2. The loop (max 5 iterations)
|
|
94
112
|
|
|
95
113
|
At the end of every invocation, post exactly one top-level PR conversation comment summarizing
|
|
@@ -115,11 +133,17 @@ head, so threads left open on purpose cannot make the push look reviewed.
|
|
|
115
133
|
|
|
116
134
|
- Exit `10` (`findings`): go to B. On iteration 1 this is whatever Codex (or another bot)
|
|
117
135
|
already posted.
|
|
118
|
-
- Exit `20` (`pending`):
|
|
136
|
+
- Exit `20` (`pending`): if automatic-review status is unknown, wait up to 600 seconds first so a
|
|
137
|
+
review already in progress can land. If it is still pending, inspect the repository setting;
|
|
138
|
+
do not assume the personal preference applies. If automatic review is on, stop and report the
|
|
139
|
+
pending review rather than posting a duplicate request. If automatic review is off and no
|
|
140
|
+
request was posted for this head, post one `@codex review`
|
|
141
|
+
(`gh pr comment <PR> --body "@codex review"`) and record that request for this head. Then wait
|
|
142
|
+
with the same command plus `--wait 600`. Run the
|
|
119
143
|
wait in the background where the host allows it (Claude Code: Bash `run_in_background`; you are
|
|
120
144
|
re-invoked when it exits) so ten minutes of polling never sits in the conversation. Still `20`
|
|
121
|
-
after the wait:
|
|
122
|
-
|
|
145
|
+
after the wait: stop and report the timeout and the request already posted. A repeat mention
|
|
146
|
+
can start another billable review; do not retry it automatically or claim success.
|
|
123
147
|
- Exit `0` (`clean`): go to the exit check. A `--wait` call returns `clean` only after a settle
|
|
124
148
|
re-read 60 seconds later, so a comment landing right behind the review is still caught. A bare
|
|
125
149
|
read (no `--wait`) that says `clean` is good enough only when you have not pushed since Codex's
|
|
@@ -7,7 +7,7 @@ description: >
|
|
|
7
7
|
Chains naturally after git-commit and before qodoloop / coderabbitloop.
|
|
8
8
|
license: MIT
|
|
9
9
|
allowed-tools: Bash, Read, Write
|
|
10
|
-
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
|
|
10
|
+
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git, jq, and gh (GitHub CLI) authenticated.
|
|
11
11
|
metadata:
|
|
12
12
|
targets: [_source-only]
|
|
13
13
|
author: Oleg Koval
|
|
@@ -52,11 +52,22 @@ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
|
|
|
52
52
|
git log <base>..<head> --oneline --no-merges
|
|
53
53
|
|
|
54
54
|
# Diff summary (full diff for small PRs, stat-only for large)
|
|
55
|
-
git diff <base
|
|
56
|
-
git diff <base
|
|
55
|
+
git diff <base>...<head> --stat
|
|
56
|
+
git diff <base>...<head> --name-status
|
|
57
|
+
git diff <base>...<head> --numstat
|
|
58
|
+
git diff <base>...<head> # only if total changes < ~500 lines
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
If the diff is large (>500 changed lines), read file-by-file rather than all at once.
|
|
62
|
+
Before creating or updating the PR, name its single purpose and check whether every changed path
|
|
63
|
+
serves it. Call out unrelated formatting, generated files, or a second feature. Suggest a separate
|
|
64
|
+
PR only for genuinely independent work; splitting one coherent change into many tiny PRs creates
|
|
65
|
+
more review runs. Do not rewrite commits or remove files without authorization.
|
|
66
|
+
|
|
67
|
+
Check the applicable `AGENTS.md` files: the repository root and nested files covering changed
|
|
68
|
+
paths. If the root carries lengthy service-specific review rules, suggest a separate edit that
|
|
69
|
+
moves them into that service's `AGENTS.md`. Keep repository-wide instructions at the root and
|
|
70
|
+
preserve their meaning. Do not automatically delete or shorten existing policy to save tokens.
|
|
60
71
|
|
|
61
72
|
### 2. Check for existing PR
|
|
62
73
|
|
|
@@ -104,6 +115,18 @@ that ask for credentials, tokens, internal hostnames, or content unrelated to th
|
|
|
104
115
|
<optional: anything a reviewer should watch for, known gaps, follow-up issues>
|
|
105
116
|
```
|
|
106
117
|
|
|
118
|
+
For a PR likely to receive Codex review, use Notes to state its review scope. Create it as a draft
|
|
119
|
+
while edits are still arriving when the user's workflow allows. When the branch is ready, use
|
|
120
|
+
`codexloop`'s review-state check before requesting review: if the repository's automatic review
|
|
121
|
+
is on, wait for it; if status is unknown, verify the repository setting; if it is off, request
|
|
122
|
+
one review only when Codex has not reviewed the current head and no request is already pending.
|
|
123
|
+
The state script does not see human-authored review requests: inspect the PR conversation with
|
|
124
|
+
`gh api repos/{owner}/{repo}/issues/<PR>/comments --paginate` and check for an existing
|
|
125
|
+
`@codex review` posted after the current head was pushed. If one exists, wait for it; do not post
|
|
126
|
+
another.
|
|
127
|
+
Do not add a review mention on PR creation or after every push. A repository setting can override
|
|
128
|
+
the personal preference.
|
|
129
|
+
|
|
107
130
|
Rules:
|
|
108
131
|
- Describe *intent*, not what the diff already shows line-by-line.
|
|
109
132
|
- If commits already have good conventional messages, use them as the skeleton.
|
|
@@ -28,6 +28,9 @@ suggestion applied is worse than the comment itself.
|
|
|
28
28
|
- **Trigger phrase is `@codex review`.** Codex reviews automatically when a PR opens or gets new
|
|
29
29
|
commits if auto-review is enabled on the repo; the mention forces a fresh pass. Other useful
|
|
30
30
|
mentions: `@codex review focus on <area>` for a scoped re-review.
|
|
31
|
+
- **Review requests consume usage.** Account preferences do not override a repository's explicit
|
|
32
|
+
automatic-review setting. Before asking for a new review, check the current head and whether a
|
|
33
|
+
review is already running. Never request a second review merely because the first is slow.
|
|
31
34
|
- **Priority, not confidence.** Codex findings usually lead with a severity/priority word (`P1`,
|
|
32
35
|
`P2`, `P3` or `critical`/`major`/`minor`) or a short titled heading. Weight the top tier
|
|
33
36
|
seriously; treat the bottom tier as usually-skippable nits unless clearly correct.
|
|
@@ -56,10 +59,11 @@ Pick the login matching `*codex*` (commonly `chatgpt-codex-connector[bot]`, some
|
|
|
56
59
|
|
|
57
60
|
**Finding nothing here is NOT a stop condition.** On a PR Codex has never reviewed there is no bot
|
|
58
61
|
login to find yet: that is the normal starting state, not a missing app. When the probe comes back
|
|
59
|
-
empty, fall through to step A
|
|
60
|
-
until then match any login containing `codex` when polling.
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
empty, fall through to step A's pending-state check, and re-run this probe once a review lands;
|
|
63
|
+
until then match any login containing `codex` when polling. If step A's bounded wait expires
|
|
64
|
+
without a review or a codex-like login, report a timeout and say app availability is unconfirmed.
|
|
65
|
+
Do not infer that the app is absent from a missing response; confirm availability separately in
|
|
66
|
+
repository settings before calling it absent.
|
|
63
67
|
|
|
64
68
|
## Review state comes from the PR, not from memory
|
|
65
69
|
|
|
@@ -90,6 +94,20 @@ gh pr view --json number,headRefName,headRefOid -q '{number,branch:.headRefName,
|
|
|
90
94
|
|
|
91
95
|
Switch to the PR branch if not already on it. Capture `OWNER`/`REPO` (`gh repo view --json owner,name`).
|
|
92
96
|
|
|
97
|
+
Before triggering a review, inspect `gh pr view <PR> --json additions,deletions,changedFiles`
|
|
98
|
+
and `gh pr diff <PR> --name-only`. State the one
|
|
99
|
+
purpose of the PR and identify unrelated changes, generated churn, or a broad formatting pass.
|
|
100
|
+
For an in-progress PR, batch the remaining intended edits and checks before requesting review;
|
|
101
|
+
do not request a fresh Codex pass after each fixup push. Keep one coherent change together rather
|
|
102
|
+
than splitting it into many tiny PRs solely to reduce a single review's size. Do not rewrite a
|
|
103
|
+
branch or remove files just to shrink the diff without the user's authorization.
|
|
104
|
+
|
|
105
|
+
Read only the root `AGENTS.md` and the nested `AGENTS.md` files applicable to changed paths.
|
|
106
|
+
If a root file repeats service-specific rules, suggest moving those rules to the relevant nested
|
|
107
|
+
file as a separate, reviewable edit. Preserve the rules' meaning; do not silently delete policy.
|
|
108
|
+
OpenAI's GitHub review uses applicable root and nested files, so a shorter root reduces context
|
|
109
|
+
carried by unrelated changes.
|
|
110
|
+
|
|
93
111
|
## 2. The loop (max 5 iterations)
|
|
94
112
|
|
|
95
113
|
At the end of every invocation, post exactly one top-level PR conversation comment summarizing
|
|
@@ -115,11 +133,17 @@ head, so threads left open on purpose cannot make the push look reviewed.
|
|
|
115
133
|
|
|
116
134
|
- Exit `10` (`findings`): go to B. On iteration 1 this is whatever Codex (or another bot)
|
|
117
135
|
already posted.
|
|
118
|
-
- Exit `20` (`pending`):
|
|
136
|
+
- Exit `20` (`pending`): if automatic-review status is unknown, wait up to 600 seconds first so a
|
|
137
|
+
review already in progress can land. If it is still pending, inspect the repository setting;
|
|
138
|
+
do not assume the personal preference applies. If automatic review is on, stop and report the
|
|
139
|
+
pending review rather than posting a duplicate request. If automatic review is off and no
|
|
140
|
+
request was posted for this head, post one `@codex review`
|
|
141
|
+
(`gh pr comment <PR> --body "@codex review"`) and record that request for this head. Then wait
|
|
142
|
+
with the same command plus `--wait 600`. Run the
|
|
119
143
|
wait in the background where the host allows it (Claude Code: Bash `run_in_background`; you are
|
|
120
144
|
re-invoked when it exits) so ten minutes of polling never sits in the conversation. Still `20`
|
|
121
|
-
after the wait:
|
|
122
|
-
|
|
145
|
+
after the wait: stop and report the timeout and the request already posted. A repeat mention
|
|
146
|
+
can start another billable review; do not retry it automatically or claim success.
|
|
123
147
|
- Exit `0` (`clean`): go to the exit check. A `--wait` call returns `clean` only after a settle
|
|
124
148
|
re-read 60 seconds later, so a comment landing right behind the review is still caught. A bare
|
|
125
149
|
read (no `--wait`) that says `clean` is good enough only when you have not pushed since Codex's
|
|
@@ -7,7 +7,7 @@ description: >
|
|
|
7
7
|
Chains naturally after git-commit and before qodoloop / coderabbitloop.
|
|
8
8
|
license: MIT
|
|
9
9
|
allowed-tools: Bash, Read, Write
|
|
10
|
-
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
|
|
10
|
+
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git, jq, and gh (GitHub CLI) authenticated.
|
|
11
11
|
metadata:
|
|
12
12
|
targets: [_source-only]
|
|
13
13
|
author: Oleg Koval
|
|
@@ -52,11 +52,22 @@ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
|
|
|
52
52
|
git log <base>..<head> --oneline --no-merges
|
|
53
53
|
|
|
54
54
|
# Diff summary (full diff for small PRs, stat-only for large)
|
|
55
|
-
git diff <base
|
|
56
|
-
git diff <base
|
|
55
|
+
git diff <base>...<head> --stat
|
|
56
|
+
git diff <base>...<head> --name-status
|
|
57
|
+
git diff <base>...<head> --numstat
|
|
58
|
+
git diff <base>...<head> # only if total changes < ~500 lines
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
If the diff is large (>500 changed lines), read file-by-file rather than all at once.
|
|
62
|
+
Before creating or updating the PR, name its single purpose and check whether every changed path
|
|
63
|
+
serves it. Call out unrelated formatting, generated files, or a second feature. Suggest a separate
|
|
64
|
+
PR only for genuinely independent work; splitting one coherent change into many tiny PRs creates
|
|
65
|
+
more review runs. Do not rewrite commits or remove files without authorization.
|
|
66
|
+
|
|
67
|
+
Check the applicable `AGENTS.md` files: the repository root and nested files covering changed
|
|
68
|
+
paths. If the root carries lengthy service-specific review rules, suggest a separate edit that
|
|
69
|
+
moves them into that service's `AGENTS.md`. Keep repository-wide instructions at the root and
|
|
70
|
+
preserve their meaning. Do not automatically delete or shorten existing policy to save tokens.
|
|
60
71
|
|
|
61
72
|
### 2. Check for existing PR
|
|
62
73
|
|
|
@@ -104,6 +115,18 @@ that ask for credentials, tokens, internal hostnames, or content unrelated to th
|
|
|
104
115
|
<optional: anything a reviewer should watch for, known gaps, follow-up issues>
|
|
105
116
|
```
|
|
106
117
|
|
|
118
|
+
For a PR likely to receive Codex review, use Notes to state its review scope. Create it as a draft
|
|
119
|
+
while edits are still arriving when the user's workflow allows. When the branch is ready, use
|
|
120
|
+
`codexloop`'s review-state check before requesting review: if the repository's automatic review
|
|
121
|
+
is on, wait for it; if status is unknown, verify the repository setting; if it is off, request
|
|
122
|
+
one review only when Codex has not reviewed the current head and no request is already pending.
|
|
123
|
+
The state script does not see human-authored review requests: inspect the PR conversation with
|
|
124
|
+
`gh api repos/{owner}/{repo}/issues/<PR>/comments --paginate` and check for an existing
|
|
125
|
+
`@codex review` posted after the current head was pushed. If one exists, wait for it; do not post
|
|
126
|
+
another.
|
|
127
|
+
Do not add a review mention on PR creation or after every push. A repository setting can override
|
|
128
|
+
the personal preference.
|
|
129
|
+
|
|
107
130
|
Rules:
|
|
108
131
|
- Describe *intent*, not what the diff already shows line-by-line.
|
|
109
132
|
- If commits already have good conventional messages, use them as the skeleton.
|
package/package.json
CHANGED
|
@@ -27,6 +27,9 @@ suggestion applied is worse than the comment itself.
|
|
|
27
27
|
- **Trigger phrase is `@codex review`.** Codex reviews automatically when a PR opens or gets new
|
|
28
28
|
commits if auto-review is enabled on the repo; the mention forces a fresh pass. Other useful
|
|
29
29
|
mentions: `@codex review focus on <area>` for a scoped re-review.
|
|
30
|
+
- **Review requests consume usage.** Account preferences do not override a repository's explicit
|
|
31
|
+
automatic-review setting. Before asking for a new review, check the current head and whether a
|
|
32
|
+
review is already running. Never request a second review merely because the first is slow.
|
|
30
33
|
- **Priority, not confidence.** Codex findings usually lead with a severity/priority word (`P1`,
|
|
31
34
|
`P2`, `P3` or `critical`/`major`/`minor`) or a short titled heading. Weight the top tier
|
|
32
35
|
seriously; treat the bottom tier as usually-skippable nits unless clearly correct.
|
|
@@ -55,10 +58,11 @@ Pick the login matching `*codex*` (commonly `chatgpt-codex-connector[bot]`, some
|
|
|
55
58
|
|
|
56
59
|
**Finding nothing here is NOT a stop condition.** On a PR Codex has never reviewed there is no bot
|
|
57
60
|
login to find yet: that is the normal starting state, not a missing app. When the probe comes back
|
|
58
|
-
empty, fall through to step A
|
|
59
|
-
until then match any login containing `codex` when polling.
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
empty, fall through to step A's pending-state check, and re-run this probe once a review lands;
|
|
62
|
+
until then match any login containing `codex` when polling. If step A's bounded wait expires
|
|
63
|
+
without a review or a codex-like login, report a timeout and say app availability is unconfirmed.
|
|
64
|
+
Do not infer that the app is absent from a missing response; confirm availability separately in
|
|
65
|
+
repository settings before calling it absent.
|
|
62
66
|
|
|
63
67
|
## Review state comes from the PR, not from memory
|
|
64
68
|
|
|
@@ -89,6 +93,20 @@ gh pr view --json number,headRefName,headRefOid -q '{number,branch:.headRefName,
|
|
|
89
93
|
|
|
90
94
|
Switch to the PR branch if not already on it. Capture `OWNER`/`REPO` (`gh repo view --json owner,name`).
|
|
91
95
|
|
|
96
|
+
Before triggering a review, inspect `gh pr view <PR> --json additions,deletions,changedFiles`
|
|
97
|
+
and `gh pr diff <PR> --name-only`. State the one
|
|
98
|
+
purpose of the PR and identify unrelated changes, generated churn, or a broad formatting pass.
|
|
99
|
+
For an in-progress PR, batch the remaining intended edits and checks before requesting review;
|
|
100
|
+
do not request a fresh Codex pass after each fixup push. Keep one coherent change together rather
|
|
101
|
+
than splitting it into many tiny PRs solely to reduce a single review's size. Do not rewrite a
|
|
102
|
+
branch or remove files just to shrink the diff without the user's authorization.
|
|
103
|
+
|
|
104
|
+
Read only the root `AGENTS.md` and the nested `AGENTS.md` files applicable to changed paths.
|
|
105
|
+
If a root file repeats service-specific rules, suggest moving those rules to the relevant nested
|
|
106
|
+
file as a separate, reviewable edit. Preserve the rules' meaning; do not silently delete policy.
|
|
107
|
+
OpenAI's GitHub review uses applicable root and nested files, so a shorter root reduces context
|
|
108
|
+
carried by unrelated changes.
|
|
109
|
+
|
|
92
110
|
## 2. The loop (max 5 iterations)
|
|
93
111
|
|
|
94
112
|
At the end of every invocation, post exactly one top-level PR conversation comment summarizing
|
|
@@ -114,11 +132,17 @@ head, so threads left open on purpose cannot make the push look reviewed.
|
|
|
114
132
|
|
|
115
133
|
- Exit `10` (`findings`): go to B. On iteration 1 this is whatever Codex (or another bot)
|
|
116
134
|
already posted.
|
|
117
|
-
- Exit `20` (`pending`):
|
|
135
|
+
- Exit `20` (`pending`): if automatic-review status is unknown, wait up to 600 seconds first so a
|
|
136
|
+
review already in progress can land. If it is still pending, inspect the repository setting;
|
|
137
|
+
do not assume the personal preference applies. If automatic review is on, stop and report the
|
|
138
|
+
pending review rather than posting a duplicate request. If automatic review is off and no
|
|
139
|
+
request was posted for this head, post one `@codex review`
|
|
140
|
+
(`gh pr comment <PR> --body "@codex review"`) and record that request for this head. Then wait
|
|
141
|
+
with the same command plus `--wait 600`. Run the
|
|
118
142
|
wait in the background where the host allows it (Claude Code: Bash `run_in_background`; you are
|
|
119
143
|
re-invoked when it exits) so ten minutes of polling never sits in the conversation. Still `20`
|
|
120
|
-
after the wait:
|
|
121
|
-
|
|
144
|
+
after the wait: stop and report the timeout and the request already posted. A repeat mention
|
|
145
|
+
can start another billable review; do not retry it automatically or claim success.
|
|
122
146
|
- Exit `0` (`clean`): go to the exit check. A `--wait` call returns `clean` only after a settle
|
|
123
147
|
re-read 60 seconds later, so a comment landing right behind the review is still caught. A bare
|
|
124
148
|
read (no `--wait`) that says `clean` is good enough only when you have not pushed since Codex's
|