@olegkoval/agent-skills 1.71.2 → 1.73.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/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +6 -5
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/project-rules.md +48 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/codex-workflow.md +2 -2
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/github-post.md +37 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +4 -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/lekker-review/README.md +2 -2
- package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +6 -5
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/project-rules.md +48 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/codex-workflow.md +2 -2
- package/plugins/olko-github-pr/skills/lekker-review/references/github-post.md +37 -1
- package/plugins/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +4 -3
- package/plugins/olko-github-pr/skills/lekker-review/workflow.js +28 -8
- 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
|
@@ -434,7 +434,7 @@ skip the review because the log failed, just say `run log unavailable`.
|
|
|
434
434
|
| Context: issue-tracker/CI/diff/existing-reviews | always | always | always | always |
|
|
435
435
|
| Context: chat/docs/framework-docs/monitoring/prior-review-memory (optional, MCP-dependent) | skip | skip | included | included + broader recall |
|
|
436
436
|
| Worktree + static checks | included (`npm ci` per changed lockfile) | skip (WORKTREE_PATH=null) unless `--fix` | included | included |
|
|
437
|
-
| Review agents | 1 deps checklist | 2 triage (haiku)
|
|
437
|
+
| Review agents | 1 deps checklist | 2 triage (haiku) + project-rules (sonnet) | 5 specialists + project-rules (sonnet) | 5 specialists + project-rules (sonnet) |
|
|
438
438
|
| Per-finding verification | none | Criticals + Importants | Criticals + Importants | Criticals + Importants |
|
|
439
439
|
| Completeness critic | skip | skip | skip | included |
|
|
440
440
|
| Proof-of-bug (failing test per Critical or composed-boundary Important) | skip | skip | included (max 5) | included (max 5) |
|
|
@@ -767,8 +767,8 @@ must pass it, or the workflow throws on its missing-args guard.
|
|
|
767
767
|
|
|
768
768
|
Two optional args tune concurrency; omit both unless a run needs it:
|
|
769
769
|
|
|
770
|
-
- `reviewBatchPlan` - batch sizes for the review dimensions, default `[
|
|
771
|
-
(all
|
|
770
|
+
- `reviewBatchPlan` - batch sizes for the review dimensions, default `[6]`
|
|
771
|
+
(all six at once). The last entry repeats to cover any remainder, so
|
|
772
772
|
`[2]` would mean two at a time.
|
|
773
773
|
- `maxConcurrent` - cap for the per-finding fan-outs (verify, critic, prove),
|
|
774
774
|
default `5`.
|
|
@@ -780,8 +780,9 @@ The workflow runs three phases:
|
|
|
780
780
|
|
|
781
781
|
- **Review:** deps uses the single `deps` checklist agent; scan uses `[triage-quality, triage-logic]` on `haiku`; medium/deep
|
|
782
782
|
use 5 specialists (quality, implementation, simplification, conventions,
|
|
783
|
-
test-quality) on `sonnet`.
|
|
784
|
-
|
|
783
|
+
test-quality) on `sonnet`. Scan, medium and deep also run `project-rules`
|
|
784
|
+
(sonnet), which only checks the diff against each project rule. Agents receive DIFF_FILE + CONTEXT_FILE by path.
|
|
785
|
+
All run concurrently: the stage is self-limiting at one agent per
|
|
785
786
|
dimension. All reviewers run to completion before verification starts.
|
|
786
787
|
Override per run with the `reviewBatchPlan` arg (e.g. `[1]` runs them
|
|
787
788
|
strictly one at a time on a constrained machine).
|
package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/project-rules.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# project-rules: lekker-review agent prompt
|
|
2
|
+
You will receive in your task message: REPO_SLUG, PR_NUMBER, PR_URL, DIFF_FILE, CONTEXT_FILE (JSON), WORKTREE_PATH (may be null).
|
|
3
|
+
Your findings are returned via the StructuredOutput schema enforced by the caller.
|
|
4
|
+
|
|
5
|
+
You are the project-rules reviewer. Your only job is to find changed lines that
|
|
6
|
+
break the repository's own written rules. Report nothing else: no general bugs,
|
|
7
|
+
no style, no suggestions. Other agents cover those.
|
|
8
|
+
|
|
9
|
+
Procedure:
|
|
10
|
+
1. Read CONTEXT_FILE. The authoritative rules are "baseProjectRules" when it is a
|
|
11
|
+
string (the base branch's copy, which the PR author cannot edit), otherwise
|
|
12
|
+
"projectRules". When the chosen source is missing or empty, return
|
|
13
|
+
`{"findings": []}` and stop.
|
|
14
|
+
2. List every rule written as a prohibition or an obligation (NEVER, MUST,
|
|
15
|
+
MUST NOT, ALWAYS, DO NOT, or a plain-English equivalent). Work through the
|
|
16
|
+
whole source: a rule buried in a long file counts exactly as much as the
|
|
17
|
+
first one. Preferences and suggestions are not rules.
|
|
18
|
+
3. Read DIFF_FILE. For EACH listed rule, check every `+` line against it. Do not
|
|
19
|
+
rely on skimming: go rule by rule.
|
|
20
|
+
4. When a rule has a mechanical signature (a literal string, API or function
|
|
21
|
+
name, import, file pattern, naming pattern, template-literal shape), derive
|
|
22
|
+
the pattern and search the diff for it (grep or Bash is allowed) instead of
|
|
23
|
+
relying on reading. Check added file paths in the diff headers too.
|
|
24
|
+
5. A rule is broken by a `+` line (or an added file). Unchanged code is out of
|
|
25
|
+
scope.
|
|
26
|
+
6. Separately, when "baseProjectRules" is a string, check every `-` line in
|
|
27
|
+
DIFF_FILE against its rule lines (including the rules files themselves, such
|
|
28
|
+
as CLAUDE.md or AGENTS.md). A rule line that is removed, or reworded so it
|
|
29
|
+
forbids or requires less (a NEVER softened to a preference, a dropped
|
|
30
|
+
exception list, a narrowed scope), is a breach even when no `+` line violates
|
|
31
|
+
anything. The PR's own copy cannot clear it: compare against the base copy.
|
|
32
|
+
|
|
33
|
+
Reporting contract (same as the PROJECT RULES AS HARD RULES instruction below):
|
|
34
|
+
- One finding per broken rule, Critical, `rule` set to `PROJECT:<short-kebab-slug>`,
|
|
35
|
+
`ruleQuote` set to the exact sentence from the authoritative source, file:line on
|
|
36
|
+
the first violating line, every other violating site in `otherInstances`.
|
|
37
|
+
- When the diff deletes or weakens a rule line that is in "baseProjectRules"
|
|
38
|
+
(procedure step 6), report an Important finding with `rule`
|
|
39
|
+
"weakens-project-rule", `ruleQuote` set to the exact base-branch sentence,
|
|
40
|
+
file:line on the removed or reworded line, and `badCode` set to the verbatim
|
|
41
|
+
`-` line (plus the replacing `+` line when there is one). `fix` is to restore
|
|
42
|
+
the rule or to state why the project dropped it.
|
|
43
|
+
- Never quote a rule that is not in the authoritative source.
|
|
44
|
+
- `badCode` is REQUIRED: the verbatim violating line copied from the diff. `fix`
|
|
45
|
+
is REQUIRED: a concrete drop-in replacement that follows the rule. If you cannot
|
|
46
|
+
quote and fix it, drop it.
|
|
47
|
+
|
|
48
|
+
CI status, acceptance criteria and existing reviews are not your concern.
|
|
@@ -66,9 +66,9 @@ unavailable; do not infer what it meant from prose.
|
|
|
66
66
|
Select dimensions exactly as the Claude workflow does:
|
|
67
67
|
|
|
68
68
|
- deps: `deps` (single checklist agent; no verifier, no prover)
|
|
69
|
-
- scan: `triage-quality`, `triage-logic`
|
|
69
|
+
- scan: `triage-quality`, `triage-logic`, `project-rules`
|
|
70
70
|
- medium/deep: `quality`, `implementation`, `simplification`, `conventions`,
|
|
71
|
-
`test-quality`
|
|
71
|
+
`test-quality`, `project-rules`
|
|
72
72
|
|
|
73
73
|
For each dimension, spawn a `default` read-only agent with the following
|
|
74
74
|
bounded task:
|
|
@@ -104,6 +104,38 @@ Rules:
|
|
|
104
104
|
Keep the body itself under ~2,500 characters. If it is longer, the asks are
|
|
105
105
|
buried: cut prose, never cut the numbered asks.
|
|
106
106
|
|
|
107
|
+
**Open-source footer:** when the repo is open source, append the footer
|
|
108
|
+
below after the last section of the body and before the closer. Never add it
|
|
109
|
+
to a private repo. Open source means the repo is public:
|
|
110
|
+
`gh repo view <REPO_SLUG> --json isPrivate --jq '.isPrivate|not'`
|
|
111
|
+
must print `true`. Any other output (private, error) means no footer. Run
|
|
112
|
+
this check in the same command sequence that writes the payload, immediately
|
|
113
|
+
before posting, and build the footer from that result alone: never reuse an
|
|
114
|
+
earlier visibility answer. Never add it to inline comments. It does not count toward the
|
|
115
|
+
~2,500-character budget, and it carries no praise, so the no-praise rule below
|
|
116
|
+
is not affected. Post it verbatim, with no em dashes:
|
|
117
|
+
|
|
118
|
+
````markdown
|
|
119
|
+
---
|
|
120
|
+
<sub>Reviewed with the [lekker-review skill](https://github.com/oleg-koval/agent-skills/tree/main/plugins/olko-github-pr/skills/lekker-review) · [skills.olegkoval.com](https://skills.olegkoval.com)</sub>
|
|
121
|
+
|
|
122
|
+
<details>
|
|
123
|
+
<summary>Install the review skill</summary>
|
|
124
|
+
|
|
125
|
+
In Claude Code:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
/plugin marketplace add oleg-koval/agent-skills
|
|
129
|
+
/plugin install olko-github-pr@olko-agent-skills
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then run `/olko-github-pr:lekker-review <PR url>`.
|
|
133
|
+
|
|
134
|
+
- Skill source: https://github.com/oleg-koval/agent-skills/tree/main/plugins/olko-github-pr/skills/lekker-review
|
|
135
|
+
- Catalog and other install options: https://skills.olegkoval.com
|
|
136
|
+
</details>
|
|
137
|
+
````
|
|
138
|
+
|
|
107
139
|
**Closer:** when `CLOSER` is set (SKILL.md Step 3), append a blank line and
|
|
108
140
|
`CLOSER.md_github` as the very last lines of the body. It does not count
|
|
109
141
|
toward the ~2,500-character budget and is exempt from the no-praise rule
|
|
@@ -201,7 +233,11 @@ If the user asks to shorten, reword, or re-scope the comments after posting:
|
|
|
201
233
|
|
|
202
234
|
- The review-level `body` alone can be edited in place:
|
|
203
235
|
`gh api repos/<REPO_SLUG>/pulls/<PR_NUMBER>/reviews/<REVIEW_ID> --method PUT --input <json with {"body": ...}>`
|
|
204
|
-
Inline comments survive this untouched.
|
|
236
|
+
Inline comments survive this untouched. A body-only PUT replaces the whole
|
|
237
|
+
body, so the replacement must carry the footer again: re-run the visibility
|
|
238
|
+
check from Step 1 and append the footer after the last section (before the
|
|
239
|
+
closer) when the repo is public, and leave it out when it is not. Never keep
|
|
240
|
+
the footer from the old body without rechecking.
|
|
205
241
|
- **Inline comment bodies cannot be reliably edited on a pending review** --
|
|
206
242
|
`PATCH /pulls/comments/{id}` targets submitted comments. To change them,
|
|
207
243
|
DELETE the pending review and POST a fresh one:
|
|
@@ -335,8 +335,8 @@ console.log('\ndeps depth: routing, classifier, line validation')
|
|
|
335
335
|
const dimensionsFor = new Function(dimsSrc + '\nreturn dimensionsFor')()
|
|
336
336
|
const M = { review: 'r', triage: 't' }
|
|
337
337
|
check('deps runs exactly one agent', dimensionsFor('deps', M).map(d => d.file), ['deps.md'])
|
|
338
|
-
check('scan
|
|
339
|
-
check('medium
|
|
338
|
+
check('scan runs the triage pair plus project-rules', dimensionsFor('scan', M).map(d => d.key), ['triage-quality', 'triage-logic', 'project-rules'])
|
|
339
|
+
check('medium runs five specialists plus project-rules', dimensionsFor('medium', M).length, 6)
|
|
340
340
|
check('every dimension prompt file exists',
|
|
341
341
|
['deps', 'scan', 'medium'].flatMap(d => dimensionsFor(d, M)).every(d => existsSync(join(SKILL, 'references', 'agents', d.file))), true)
|
|
342
342
|
}
|
|
@@ -871,7 +871,8 @@ function liftBlock(name) {
|
|
|
871
871
|
const liftBlockOr = name => { try { return liftBlock(name) } catch { return `const ${name} = ''\n` } }
|
|
872
872
|
const buildPrompt = new Function(
|
|
873
873
|
'dim', 'SUPPRESSED', 'prevSha',
|
|
874
|
-
[liftBlockOr('PROJECT_RULE_DIMENSIONS'), liftBlockOr('
|
|
874
|
+
[liftBlockOr('PROJECT_RULE_DIMENSIONS'), liftBlockOr('PROJECT_RULE_CORE'), liftBlockOr('IGNORE_ENTRY_NOTE'),
|
|
875
|
+
liftBlockOr('PROJECT_RULE_INSTRUCTION'), liftBlockOr('PROJECT_RULE_ONLY_INSTRUCTION'), liftConst('BUG_CLASS_INSTRUCTION'),
|
|
875
876
|
`const targetMetadata = '{}', promptDir = 'p', repoSlug = 'o/r', prNumber = 1, prUrl = 'u',
|
|
876
877
|
diffFile = 'd', contextFile = 'c', wtDisplay = 'w'`,
|
|
877
878
|
lift('reviewPrompt'), 'return reviewPrompt(dim)'].join('\n'),
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
FAANG-quality PR code review for GitHub. It gathers the context a human reviewer
|
|
4
4
|
would gather and checks the branch out into an isolated worktree when the depth
|
|
5
|
-
requires one. `scan` runs two triage agents. `medium` and
|
|
6
|
-
`deep` run five specialists and attempt proofs for at most five non-rule
|
|
5
|
+
requires one. `scan` runs two triage agents plus project-rules. `medium` and
|
|
6
|
+
`deep` run five specialists plus project-rules and attempt proofs for at most five non-rule
|
|
7
7
|
Critical findings.
|
|
8
8
|
|
|
9
9
|

|
|
@@ -433,7 +433,7 @@ skip the review because the log failed, just say `run log unavailable`.
|
|
|
433
433
|
| Context: issue-tracker/CI/diff/existing-reviews | always | always | always | always |
|
|
434
434
|
| Context: chat/docs/framework-docs/monitoring/prior-review-memory (optional, MCP-dependent) | skip | skip | included | included + broader recall |
|
|
435
435
|
| Worktree + static checks | included (`npm ci` per changed lockfile) | skip (WORKTREE_PATH=null) unless `--fix` | included | included |
|
|
436
|
-
| Review agents | 1 deps checklist | 2 triage (haiku)
|
|
436
|
+
| Review agents | 1 deps checklist | 2 triage (haiku) + project-rules (sonnet) | 5 specialists + project-rules (sonnet) | 5 specialists + project-rules (sonnet) |
|
|
437
437
|
| Per-finding verification | none | Criticals + Importants | Criticals + Importants | Criticals + Importants |
|
|
438
438
|
| Completeness critic | skip | skip | skip | included |
|
|
439
439
|
| Proof-of-bug (failing test per Critical or composed-boundary Important) | skip | skip | included (max 5) | included (max 5) |
|
|
@@ -766,8 +766,8 @@ must pass it, or the workflow throws on its missing-args guard.
|
|
|
766
766
|
|
|
767
767
|
Two optional args tune concurrency; omit both unless a run needs it:
|
|
768
768
|
|
|
769
|
-
- `reviewBatchPlan` - batch sizes for the review dimensions, default `[
|
|
770
|
-
(all
|
|
769
|
+
- `reviewBatchPlan` - batch sizes for the review dimensions, default `[6]`
|
|
770
|
+
(all six at once). The last entry repeats to cover any remainder, so
|
|
771
771
|
`[2]` would mean two at a time.
|
|
772
772
|
- `maxConcurrent` - cap for the per-finding fan-outs (verify, critic, prove),
|
|
773
773
|
default `5`.
|
|
@@ -779,8 +779,9 @@ The workflow runs three phases:
|
|
|
779
779
|
|
|
780
780
|
- **Review:** deps uses the single `deps` checklist agent; scan uses `[triage-quality, triage-logic]` on `haiku`; medium/deep
|
|
781
781
|
use 5 specialists (quality, implementation, simplification, conventions,
|
|
782
|
-
test-quality) on `sonnet`.
|
|
783
|
-
|
|
782
|
+
test-quality) on `sonnet`. Scan, medium and deep also run `project-rules`
|
|
783
|
+
(sonnet), which only checks the diff against each project rule. Agents receive DIFF_FILE + CONTEXT_FILE by path.
|
|
784
|
+
All run concurrently: the stage is self-limiting at one agent per
|
|
784
785
|
dimension. All reviewers run to completion before verification starts.
|
|
785
786
|
Override per run with the `reviewBatchPlan` arg (e.g. `[1]` runs them
|
|
786
787
|
strictly one at a time on a constrained machine).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# project-rules: lekker-review agent prompt
|
|
2
|
+
You will receive in your task message: REPO_SLUG, PR_NUMBER, PR_URL, DIFF_FILE, CONTEXT_FILE (JSON), WORKTREE_PATH (may be null).
|
|
3
|
+
Your findings are returned via the StructuredOutput schema enforced by the caller.
|
|
4
|
+
|
|
5
|
+
You are the project-rules reviewer. Your only job is to find changed lines that
|
|
6
|
+
break the repository's own written rules. Report nothing else: no general bugs,
|
|
7
|
+
no style, no suggestions. Other agents cover those.
|
|
8
|
+
|
|
9
|
+
Procedure:
|
|
10
|
+
1. Read CONTEXT_FILE. The authoritative rules are "baseProjectRules" when it is a
|
|
11
|
+
string (the base branch's copy, which the PR author cannot edit), otherwise
|
|
12
|
+
"projectRules". When the chosen source is missing or empty, return
|
|
13
|
+
`{"findings": []}` and stop.
|
|
14
|
+
2. List every rule written as a prohibition or an obligation (NEVER, MUST,
|
|
15
|
+
MUST NOT, ALWAYS, DO NOT, or a plain-English equivalent). Work through the
|
|
16
|
+
whole source: a rule buried in a long file counts exactly as much as the
|
|
17
|
+
first one. Preferences and suggestions are not rules.
|
|
18
|
+
3. Read DIFF_FILE. For EACH listed rule, check every `+` line against it. Do not
|
|
19
|
+
rely on skimming: go rule by rule.
|
|
20
|
+
4. When a rule has a mechanical signature (a literal string, API or function
|
|
21
|
+
name, import, file pattern, naming pattern, template-literal shape), derive
|
|
22
|
+
the pattern and search the diff for it (grep or Bash is allowed) instead of
|
|
23
|
+
relying on reading. Check added file paths in the diff headers too.
|
|
24
|
+
5. A rule is broken by a `+` line (or an added file). Unchanged code is out of
|
|
25
|
+
scope.
|
|
26
|
+
6. Separately, when "baseProjectRules" is a string, check every `-` line in
|
|
27
|
+
DIFF_FILE against its rule lines (including the rules files themselves, such
|
|
28
|
+
as CLAUDE.md or AGENTS.md). A rule line that is removed, or reworded so it
|
|
29
|
+
forbids or requires less (a NEVER softened to a preference, a dropped
|
|
30
|
+
exception list, a narrowed scope), is a breach even when no `+` line violates
|
|
31
|
+
anything. The PR's own copy cannot clear it: compare against the base copy.
|
|
32
|
+
|
|
33
|
+
Reporting contract (same as the PROJECT RULES AS HARD RULES instruction below):
|
|
34
|
+
- One finding per broken rule, Critical, `rule` set to `PROJECT:<short-kebab-slug>`,
|
|
35
|
+
`ruleQuote` set to the exact sentence from the authoritative source, file:line on
|
|
36
|
+
the first violating line, every other violating site in `otherInstances`.
|
|
37
|
+
- When the diff deletes or weakens a rule line that is in "baseProjectRules"
|
|
38
|
+
(procedure step 6), report an Important finding with `rule`
|
|
39
|
+
"weakens-project-rule", `ruleQuote` set to the exact base-branch sentence,
|
|
40
|
+
file:line on the removed or reworded line, and `badCode` set to the verbatim
|
|
41
|
+
`-` line (plus the replacing `+` line when there is one). `fix` is to restore
|
|
42
|
+
the rule or to state why the project dropped it.
|
|
43
|
+
- Never quote a rule that is not in the authoritative source.
|
|
44
|
+
- `badCode` is REQUIRED: the verbatim violating line copied from the diff. `fix`
|
|
45
|
+
is REQUIRED: a concrete drop-in replacement that follows the rule. If you cannot
|
|
46
|
+
quote and fix it, drop it.
|
|
47
|
+
|
|
48
|
+
CI status, acceptance criteria and existing reviews are not your concern.
|
|
@@ -66,9 +66,9 @@ unavailable; do not infer what it meant from prose.
|
|
|
66
66
|
Select dimensions exactly as the Claude workflow does:
|
|
67
67
|
|
|
68
68
|
- deps: `deps` (single checklist agent; no verifier, no prover)
|
|
69
|
-
- scan: `triage-quality`, `triage-logic`
|
|
69
|
+
- scan: `triage-quality`, `triage-logic`, `project-rules`
|
|
70
70
|
- medium/deep: `quality`, `implementation`, `simplification`, `conventions`,
|
|
71
|
-
`test-quality`
|
|
71
|
+
`test-quality`, `project-rules`
|
|
72
72
|
|
|
73
73
|
For each dimension, spawn a `default` read-only agent with the following
|
|
74
74
|
bounded task:
|
|
@@ -104,6 +104,38 @@ Rules:
|
|
|
104
104
|
Keep the body itself under ~2,500 characters. If it is longer, the asks are
|
|
105
105
|
buried: cut prose, never cut the numbered asks.
|
|
106
106
|
|
|
107
|
+
**Open-source footer:** when the repo is open source, append the footer
|
|
108
|
+
below after the last section of the body and before the closer. Never add it
|
|
109
|
+
to a private repo. Open source means the repo is public:
|
|
110
|
+
`gh repo view <REPO_SLUG> --json isPrivate --jq '.isPrivate|not'`
|
|
111
|
+
must print `true`. Any other output (private, error) means no footer. Run
|
|
112
|
+
this check in the same command sequence that writes the payload, immediately
|
|
113
|
+
before posting, and build the footer from that result alone: never reuse an
|
|
114
|
+
earlier visibility answer. Never add it to inline comments. It does not count toward the
|
|
115
|
+
~2,500-character budget, and it carries no praise, so the no-praise rule below
|
|
116
|
+
is not affected. Post it verbatim, with no em dashes:
|
|
117
|
+
|
|
118
|
+
````markdown
|
|
119
|
+
---
|
|
120
|
+
<sub>Reviewed with the [lekker-review skill](https://github.com/oleg-koval/agent-skills/tree/main/plugins/olko-github-pr/skills/lekker-review) · [skills.olegkoval.com](https://skills.olegkoval.com)</sub>
|
|
121
|
+
|
|
122
|
+
<details>
|
|
123
|
+
<summary>Install the review skill</summary>
|
|
124
|
+
|
|
125
|
+
In Claude Code:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
/plugin marketplace add oleg-koval/agent-skills
|
|
129
|
+
/plugin install olko-github-pr@olko-agent-skills
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then run `/olko-github-pr:lekker-review <PR url>`.
|
|
133
|
+
|
|
134
|
+
- Skill source: https://github.com/oleg-koval/agent-skills/tree/main/plugins/olko-github-pr/skills/lekker-review
|
|
135
|
+
- Catalog and other install options: https://skills.olegkoval.com
|
|
136
|
+
</details>
|
|
137
|
+
````
|
|
138
|
+
|
|
107
139
|
**Closer:** when `CLOSER` is set (SKILL.md Step 3), append a blank line and
|
|
108
140
|
`CLOSER.md_github` as the very last lines of the body. It does not count
|
|
109
141
|
toward the ~2,500-character budget and is exempt from the no-praise rule
|
|
@@ -201,7 +233,11 @@ If the user asks to shorten, reword, or re-scope the comments after posting:
|
|
|
201
233
|
|
|
202
234
|
- The review-level `body` alone can be edited in place:
|
|
203
235
|
`gh api repos/<REPO_SLUG>/pulls/<PR_NUMBER>/reviews/<REVIEW_ID> --method PUT --input <json with {"body": ...}>`
|
|
204
|
-
Inline comments survive this untouched.
|
|
236
|
+
Inline comments survive this untouched. A body-only PUT replaces the whole
|
|
237
|
+
body, so the replacement must carry the footer again: re-run the visibility
|
|
238
|
+
check from Step 1 and append the footer after the last section (before the
|
|
239
|
+
closer) when the repo is public, and leave it out when it is not. Never keep
|
|
240
|
+
the footer from the old body without rechecking.
|
|
205
241
|
- **Inline comment bodies cannot be reliably edited on a pending review** --
|
|
206
242
|
`PATCH /pulls/comments/{id}` targets submitted comments. To change them,
|
|
207
243
|
DELETE the pending review and POST a fresh one:
|
|
@@ -335,8 +335,8 @@ console.log('\ndeps depth: routing, classifier, line validation')
|
|
|
335
335
|
const dimensionsFor = new Function(dimsSrc + '\nreturn dimensionsFor')()
|
|
336
336
|
const M = { review: 'r', triage: 't' }
|
|
337
337
|
check('deps runs exactly one agent', dimensionsFor('deps', M).map(d => d.file), ['deps.md'])
|
|
338
|
-
check('scan
|
|
339
|
-
check('medium
|
|
338
|
+
check('scan runs the triage pair plus project-rules', dimensionsFor('scan', M).map(d => d.key), ['triage-quality', 'triage-logic', 'project-rules'])
|
|
339
|
+
check('medium runs five specialists plus project-rules', dimensionsFor('medium', M).length, 6)
|
|
340
340
|
check('every dimension prompt file exists',
|
|
341
341
|
['deps', 'scan', 'medium'].flatMap(d => dimensionsFor(d, M)).every(d => existsSync(join(SKILL, 'references', 'agents', d.file))), true)
|
|
342
342
|
}
|
|
@@ -871,7 +871,8 @@ function liftBlock(name) {
|
|
|
871
871
|
const liftBlockOr = name => { try { return liftBlock(name) } catch { return `const ${name} = ''\n` } }
|
|
872
872
|
const buildPrompt = new Function(
|
|
873
873
|
'dim', 'SUPPRESSED', 'prevSha',
|
|
874
|
-
[liftBlockOr('PROJECT_RULE_DIMENSIONS'), liftBlockOr('
|
|
874
|
+
[liftBlockOr('PROJECT_RULE_DIMENSIONS'), liftBlockOr('PROJECT_RULE_CORE'), liftBlockOr('IGNORE_ENTRY_NOTE'),
|
|
875
|
+
liftBlockOr('PROJECT_RULE_INSTRUCTION'), liftBlockOr('PROJECT_RULE_ONLY_INSTRUCTION'), liftConst('BUG_CLASS_INSTRUCTION'),
|
|
875
876
|
`const targetMetadata = '{}', promptDir = 'p', repoSlug = 'o/r', prNumber = 1, prUrl = 'u',
|
|
876
877
|
diffFile = 'd', contextFile = 'c', wtDisplay = 'w'`,
|
|
877
878
|
lift('reviewPrompt'), 'return reviewPrompt(dim)'].join('\n'),
|
|
@@ -201,6 +201,11 @@ function sameIssue(a, b) {
|
|
|
201
201
|
&& qa !== '' && qb !== '' && qa !== qb) {
|
|
202
202
|
return false
|
|
203
203
|
}
|
|
204
|
+
// One authoritative rule quote is one breach, whatever each reviewer titled it or
|
|
205
|
+
// classed it. Location is still gated by the caller's file bucket and line window.
|
|
206
|
+
if (sameProjectQuote) {
|
|
207
|
+
return true
|
|
208
|
+
}
|
|
204
209
|
// Merging two classes would send one class's instances to the other's fix.
|
|
205
210
|
if (a.bugClass && b.bugClass && a.bugClass !== b.bugClass) {
|
|
206
211
|
return false
|
|
@@ -222,9 +227,9 @@ const BUG_CLASS_INSTRUCTION = `BUG CLASS: give every finding a "bugClass" (short
|
|
|
222
227
|
+ ` "file:line" (empty array when there is none). Report the class, not just the first hit.`
|
|
223
228
|
|
|
224
229
|
const PROJECT_RULE_DIMENSIONS = ['quality', 'implementation', 'simplification', 'conventions', 'test-quality',
|
|
225
|
-
'triage-quality', 'triage-logic']
|
|
230
|
+
'triage-quality', 'triage-logic', 'project-rules']
|
|
226
231
|
|
|
227
|
-
const
|
|
232
|
+
const PROJECT_RULE_CORE = `PROJECT RULES AS HARD RULES: read "projectRules" from CONTEXT_FILE.`
|
|
228
233
|
+ ` When a changed line violates a project rule written as a prohibition or an obligation`
|
|
229
234
|
+ ` (NEVER, MUST, MUST NOT, ALWAYS, DO NOT, or a plain-English equivalent), raise a Critical`
|
|
230
235
|
+ ` finding with "rule" set to "PROJECT:<short-kebab-slug>", "ruleQuote" set to the exact`
|
|
@@ -234,8 +239,18 @@ const PROJECT_RULE_INSTRUCTION = `PROJECT RULES AS HARD RULES: read "projectRule
|
|
|
234
239
|
+ ` baseProjectRules, raise an Important finding with rule "weakens-project-rule" quoting`
|
|
235
240
|
+ ` the removed line. One finding per rule,`
|
|
236
241
|
+ ` with every other violating site in "otherInstances". Never quote a rule that is not in`
|
|
237
|
-
+ ` the authoritative source ("baseProjectRules" when it is a string, otherwise "projectRules")
|
|
238
|
-
|
|
242
|
+
+ ` the authoritative source ("baseProjectRules" when it is a string, otherwise "projectRules").`
|
|
243
|
+
|
|
244
|
+
const IGNORE_ENTRY_NOTE = ` A REVIEW.md ignore entry narrows where you look, it never disables a rule.`
|
|
245
|
+
|
|
246
|
+
const PROJECT_RULE_INSTRUCTION = PROJECT_RULE_CORE
|
|
247
|
+
+ ` Preferences and suggestions are not hard rules: report them as ordinary findings.`
|
|
248
|
+
+ IGNORE_ENTRY_NOTE
|
|
249
|
+
|
|
250
|
+
// The dedicated reviewer owns hard rules only, so it must not be told to emit preference findings.
|
|
251
|
+
const PROJECT_RULE_ONLY_INSTRUCTION = PROJECT_RULE_CORE
|
|
252
|
+
+ ` Preferences and suggestions are out of scope for you: do not report them.`
|
|
253
|
+
+ IGNORE_ENTRY_NOTE
|
|
239
254
|
|
|
240
255
|
const BUG_CLASS_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/
|
|
241
256
|
const INSTANCE_PATTERN = new RegExp(INSTANCE_PATTERN_SOURCE)
|
|
@@ -397,7 +412,10 @@ function shouldVerify(finding, depth) {
|
|
|
397
412
|
// Which reviewers run at each depth. `deps` is a PR whose only changes are
|
|
398
413
|
// lockfiles and the dependency keys of package.json: five specialists would
|
|
399
414
|
// produce a couple of notes that a single checklist agent covers, so it gets
|
|
400
|
-
// exactly one.
|
|
415
|
+
// exactly one. `project-rules` runs at every other depth: a rule sentence inside
|
|
416
|
+
// a large rules file was missed when the check was only a side duty of generalist
|
|
417
|
+
// agents. It always runs because the script cannot cheaply tell whether the
|
|
418
|
+
// context holds rules; its prompt returns no findings when they are absent.
|
|
401
419
|
function dimensionsFor(depth, MODEL) {
|
|
402
420
|
if (depth === 'deps') {
|
|
403
421
|
return [{ key: 'deps', file: 'deps.md', model: MODEL.review }]
|
|
@@ -406,6 +424,7 @@ function dimensionsFor(depth, MODEL) {
|
|
|
406
424
|
return [
|
|
407
425
|
{ key: 'triage-quality', file: 'triage-quality.md', model: MODEL.triage },
|
|
408
426
|
{ key: 'triage-logic', file: 'triage-logic.md', model: MODEL.triage },
|
|
427
|
+
{ key: 'project-rules', file: 'project-rules.md', model: MODEL.review },
|
|
409
428
|
]
|
|
410
429
|
}
|
|
411
430
|
return [
|
|
@@ -414,6 +433,7 @@ function dimensionsFor(depth, MODEL) {
|
|
|
414
433
|
{ key: 'simplification', file: 'simplification.md', model: MODEL.review },
|
|
415
434
|
{ key: 'conventions', file: 'conventions.md', model: MODEL.review },
|
|
416
435
|
{ key: 'test-quality', file: 'test-quality.md', model: MODEL.review },
|
|
436
|
+
{ key: 'project-rules', file: 'project-rules.md', model: MODEL.review },
|
|
417
437
|
]
|
|
418
438
|
}
|
|
419
439
|
|
|
@@ -586,14 +606,14 @@ if (ENGINE === 'revmux' && !findingsFile) {
|
|
|
586
606
|
throw new Error('lekker-review workflow: engine "revmux" requires findingsFile (adapter output)')
|
|
587
607
|
}
|
|
588
608
|
|
|
589
|
-
// Concurrency. The review stage is self-limiting:
|
|
609
|
+
// Concurrency. The review stage is self-limiting: six dimensions means six
|
|
590
610
|
// agents, so it runs them all at once. The other stages are not. Verify,
|
|
591
611
|
// critic and prove spawn one agent PER FINDING, so a finding-heavy PR would
|
|
592
612
|
// fan out far wider than the review that produced it, with no ceiling. Those
|
|
593
613
|
// are capped at the review stage's own width.
|
|
594
614
|
const REVIEW_PLAN = (Array.isArray(reviewBatchPlan) && reviewBatchPlan.length > 0)
|
|
595
615
|
? reviewBatchPlan
|
|
596
|
-
: [
|
|
616
|
+
: [6]
|
|
597
617
|
const FANOUT_PLAN = [Math.max(1, maxConcurrent || 5)]
|
|
598
618
|
const targetMetadata = JSON.stringify({ targetLabel })
|
|
599
619
|
|
|
@@ -678,7 +698,7 @@ const budgetAtStart = budget.spent()
|
|
|
678
698
|
prompt += ' ' + BUG_CLASS_INSTRUCTION
|
|
679
699
|
|
|
680
700
|
if (PROJECT_RULE_DIMENSIONS.includes(dim.key)) {
|
|
681
|
-
prompt += ' ' + PROJECT_RULE_INSTRUCTION
|
|
701
|
+
prompt += ' ' + (dim.key === 'project-rules' ? PROJECT_RULE_ONLY_INSTRUCTION : PROJECT_RULE_INSTRUCTION)
|
|
682
702
|
}
|
|
683
703
|
|
|
684
704
|
// The deterministic lint pre-flight has already collected every rule the
|