@olegkoval/agent-skills 1.40.0 → 1.41.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/open-source-publisher.prompt.md +3 -4
- package/.kiro/steering/open-source-publisher.md +3 -4
- package/.windsurf/rules/open-source-publisher.md +3 -4
- package/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +15 -17
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/implementation.md +2 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/prover.md +13 -10
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/quality.md +1 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/test-quality.md +7 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/triage-quality.md +1 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/verifier.md +12 -9
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/artifact-page.md +6 -1
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/output-format.md +5 -8
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +174 -0
- package/adapters/claude/olko-reflection/skills/self-critique/scripts/critique-nudge.mjs +3 -0
- package/adapters/claude/olko-release/skills/open-source-publisher/SKILL.md +4 -5
- package/adapters/cursor/olko-reflection/skills/self-critique/scripts/critique-nudge.mjs +3 -0
- package/adapters/cursor/olko-release/skills/open-source-publisher/SKILL.md +4 -5
- package/adapters/grok/olko-reflection/skills/self-critique/scripts/critique-nudge.mjs +3 -0
- package/adapters/grok/olko-release/skills/open-source-publisher/SKILL.md +4 -5
- 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 +9 -9
- package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +15 -17
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/implementation.md +2 -1
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/prover.md +13 -10
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/quality.md +1 -1
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/test-quality.md +7 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/triage-quality.md +1 -1
- package/plugins/olko-github-pr/skills/lekker-review/references/agents/verifier.md +12 -9
- package/plugins/olko-github-pr/skills/lekker-review/references/artifact-page.md +6 -1
- package/plugins/olko-github-pr/skills/lekker-review/references/output-format.md +5 -8
- package/plugins/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +174 -0
- package/plugins/olko-github-pr/skills/lekker-review/workflow.js +217 -75
- 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-reflection/skills/self-critique/scripts/critique-nudge.mjs +3 -0
- package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-release/skills/open-source-publisher/SKILL.md +4 -5
- package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
- package/scripts/lib/catalog.mjs +3 -0
|
@@ -31,12 +31,11 @@ Use this skill to audit whether an OSS repository is ready to publish, then help
|
|
|
31
31
|
5. For existing usable pieces, do not propose replacement by default. Ask a change-oriented question only when useful, for example:
|
|
32
32
|
- "You already have a terminal-style GitHub Pages site. Do you want to keep it or restyle it?"
|
|
33
33
|
- "You already have an icon and social card. Do you want a refresh, or should I leave them as-is?"
|
|
34
|
-
- "You already have a static social card. Do you want me to animate it with pixel2motion, or leave it static?"
|
|
35
34
|
- "You already have release automation. Do you want me to audit only, or also tighten it?"
|
|
36
35
|
6. Ask only for choices needed to fix missing or weak pieces:
|
|
37
36
|
- If GitHub Pages is missing or weak, ask for style: `oldschool linux`, `terminal`, `modern`, `brutalist`, `glassmorphism`, `y2k`, `hacker`, or custom.
|
|
38
37
|
- If donation wiring is missing, ask whether to enable it: `none`, `GitHub Sponsors`, `Ko-fi`, `Buy Me a Coffee`, `Open Collective`, `Thanks.dev`, or custom URL.
|
|
39
|
-
- If the repo has a generated
|
|
38
|
+
- If the repo has a generated logo or simple hero artwork supported by `nolangz/pixel2motion`, ask whether to animate it or leave it static.
|
|
40
39
|
- If the repo has no clear product essence, ask for a one-sentence positioning statement.
|
|
41
40
|
7. Implement only approved, missing, or weak work in this order:
|
|
42
41
|
- OSS governance and support files
|
|
@@ -200,8 +199,8 @@ Use `magick` or another renderer when `rsvg-convert` is unavailable.
|
|
|
200
199
|
|
|
201
200
|
Some repos benefit from a short animated preview. Keep this opt-in.
|
|
202
201
|
|
|
203
|
-
-
|
|
204
|
-
-
|
|
202
|
+
- After the user opts in during workflow step 6, animate only the approved generated logo or simple artwork.
|
|
203
|
+
- Use `nolangz/pixel2motion` as the optional dependency for that animation, animated HTML demos, and GIF/video previews.
|
|
205
204
|
- Do not auto-animate by default.
|
|
206
205
|
|
|
207
206
|
## README Standard
|
|
@@ -30,12 +30,11 @@ Use this skill to audit whether an OSS repository is ready to publish, then help
|
|
|
30
30
|
5. For existing usable pieces, do not propose replacement by default. Ask a change-oriented question only when useful, for example:
|
|
31
31
|
- "You already have a terminal-style GitHub Pages site. Do you want to keep it or restyle it?"
|
|
32
32
|
- "You already have an icon and social card. Do you want a refresh, or should I leave them as-is?"
|
|
33
|
-
- "You already have a static social card. Do you want me to animate it with pixel2motion, or leave it static?"
|
|
34
33
|
- "You already have release automation. Do you want me to audit only, or also tighten it?"
|
|
35
34
|
6. Ask only for choices needed to fix missing or weak pieces:
|
|
36
35
|
- If GitHub Pages is missing or weak, ask for style: `oldschool linux`, `terminal`, `modern`, `brutalist`, `glassmorphism`, `y2k`, `hacker`, or custom.
|
|
37
36
|
- If donation wiring is missing, ask whether to enable it: `none`, `GitHub Sponsors`, `Ko-fi`, `Buy Me a Coffee`, `Open Collective`, `Thanks.dev`, or custom URL.
|
|
38
|
-
- If the repo has a generated
|
|
37
|
+
- If the repo has a generated logo or simple hero artwork supported by `nolangz/pixel2motion`, ask whether to animate it or leave it static.
|
|
39
38
|
- If the repo has no clear product essence, ask for a one-sentence positioning statement.
|
|
40
39
|
7. Implement only approved, missing, or weak work in this order:
|
|
41
40
|
- OSS governance and support files
|
|
@@ -199,8 +198,8 @@ Use `magick` or another renderer when `rsvg-convert` is unavailable.
|
|
|
199
198
|
|
|
200
199
|
Some repos benefit from a short animated preview. Keep this opt-in.
|
|
201
200
|
|
|
202
|
-
-
|
|
203
|
-
-
|
|
201
|
+
- After the user opts in during workflow step 6, animate only the approved generated logo or simple artwork.
|
|
202
|
+
- Use `nolangz/pixel2motion` as the optional dependency for that animation, animated HTML demos, and GIF/video previews.
|
|
204
203
|
- Do not auto-animate by default.
|
|
205
204
|
|
|
206
205
|
## README Standard
|
|
@@ -29,12 +29,11 @@ Use this skill to audit whether an OSS repository is ready to publish, then help
|
|
|
29
29
|
5. For existing usable pieces, do not propose replacement by default. Ask a change-oriented question only when useful, for example:
|
|
30
30
|
- "You already have a terminal-style GitHub Pages site. Do you want to keep it or restyle it?"
|
|
31
31
|
- "You already have an icon and social card. Do you want a refresh, or should I leave them as-is?"
|
|
32
|
-
- "You already have a static social card. Do you want me to animate it with pixel2motion, or leave it static?"
|
|
33
32
|
- "You already have release automation. Do you want me to audit only, or also tighten it?"
|
|
34
33
|
6. Ask only for choices needed to fix missing or weak pieces:
|
|
35
34
|
- If GitHub Pages is missing or weak, ask for style: `oldschool linux`, `terminal`, `modern`, `brutalist`, `glassmorphism`, `y2k`, `hacker`, or custom.
|
|
36
35
|
- If donation wiring is missing, ask whether to enable it: `none`, `GitHub Sponsors`, `Ko-fi`, `Buy Me a Coffee`, `Open Collective`, `Thanks.dev`, or custom URL.
|
|
37
|
-
- If the repo has a generated
|
|
36
|
+
- If the repo has a generated logo or simple hero artwork supported by `nolangz/pixel2motion`, ask whether to animate it or leave it static.
|
|
38
37
|
- If the repo has no clear product essence, ask for a one-sentence positioning statement.
|
|
39
38
|
7. Implement only approved, missing, or weak work in this order:
|
|
40
39
|
- OSS governance and support files
|
|
@@ -198,8 +197,8 @@ Use `magick` or another renderer when `rsvg-convert` is unavailable.
|
|
|
198
197
|
|
|
199
198
|
Some repos benefit from a short animated preview. Keep this opt-in.
|
|
200
199
|
|
|
201
|
-
-
|
|
202
|
-
-
|
|
200
|
+
- After the user opts in during workflow step 6, animate only the approved generated logo or simple artwork.
|
|
201
|
+
- Use `nolangz/pixel2motion` as the optional dependency for that animation, animated HTML demos, and GIF/video previews.
|
|
203
202
|
- Do not auto-animate by default.
|
|
204
203
|
|
|
205
204
|
## README Standard
|
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
isolated worktree, gathers context from your issue tracker, chat, docs, CI
|
|
6
6
|
checks, and (optionally) production monitoring, runs 5 parallel specialized
|
|
7
7
|
review agents (quality/implementation/simplification/conventions/test-quality),
|
|
8
|
-
verifies every finding against the diff, then outputs a single unified markdown
|
|
8
|
+
verifies every verdict-affecting finding against the diff, then outputs a single unified markdown
|
|
9
9
|
review: file + risk + bad code + why it's wrong + fix, ready to paste directly
|
|
10
10
|
into GitHub. Saves every review to ~/code-reviews/*.md. Covers business logic,
|
|
11
11
|
scalability, complexity, data integrity, security, integration contracts, error
|
|
@@ -79,14 +79,11 @@ the 5 specialist agents still run and still find real bugs. They just don't
|
|
|
79
79
|
have a codified "always Critical" rule list to check against.
|
|
80
80
|
|
|
81
81
|
If any hard rule you define carries a `rule` tag (e.g. `"TS-1"`), reviewer
|
|
82
|
-
agents attach that tag to matching findings
|
|
83
|
-
|
|
84
|
-
challenges
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
your policy declares non-negotiable. A tagged finding keeps its Critical
|
|
88
|
-
severity; the workflow returns how many were exempted as `hardRuleCount`, and
|
|
89
|
-
each carries a `verifierReasoning` saying so.
|
|
82
|
+
agents attach that tag to matching findings. The verifier checks the diff
|
|
83
|
+
anchor and rule applicability, but skips its five runtime-failure challenges.
|
|
84
|
+
Those challenges cannot evaluate a standards violation. A tagged finding keeps
|
|
85
|
+
Critical severity only when both rule-specific checks pass. The workflow
|
|
86
|
+
returns the number checked as `hardRuleCount`.
|
|
90
87
|
|
|
91
88
|
`${CLAUDE_PLUGIN_ROOT}` below refers to this skill's own installed directory:
|
|
92
89
|
resolve every `references/...` and script path relative to it.
|
|
@@ -150,7 +147,7 @@ treat as a full review and leave PREV_SHA unset. Also grep the same file for
|
|
|
150
147
|
| Context: chat/docs/framework-docs/monitoring/prior-review-memory (optional, MCP-dependent) | skip | included | included + broader recall |
|
|
151
148
|
| Worktree + static checks | skip (WORKTREE_PATH=null) unless `--fix` | included | included |
|
|
152
149
|
| Review agents | 2 triage (haiku) | 5 specialists (sonnet) | 5 specialists (sonnet) |
|
|
153
|
-
| Per-finding verification |
|
|
150
|
+
| Per-finding verification | Criticals + Importants | Criticals + Importants | Criticals + Importants |
|
|
154
151
|
| Completeness critic | skip | skip | included |
|
|
155
152
|
| Proof-of-bug (failing test per Critical) | skip | included (max 5) | included (max 5) |
|
|
156
153
|
| Living review artifact | included | included | included |
|
|
@@ -298,8 +295,9 @@ The workflow runs three phases:
|
|
|
298
295
|
description/badCode/fix of the set - a Critical is never demoted by an
|
|
299
296
|
Observation someone else filed at the same line - and records every
|
|
300
297
|
contributing dimension in `agreedBy`.
|
|
301
|
-
- **Verify:**
|
|
302
|
-
|
|
298
|
+
- **Verify:** every Critical and Important is checked at every depth because it
|
|
299
|
+
can affect the verdict. Hard-rule findings (`rule` set) use the verifier's
|
|
300
|
+
diff-anchor and rule-applicability checks instead of runtime challenges.
|
|
303
301
|
Each verifier runs the five-challenge adversarial refutation from
|
|
304
302
|
`references/agents/verifier.md` against one finding, returns
|
|
305
303
|
`{verdict, newSeverity?, reasoning}`. Verifiers run `maxConcurrent` at a time
|
|
@@ -311,13 +309,13 @@ The workflow runs three phases:
|
|
|
311
309
|
one prover agent (`references/agents/prover.md`, sonnet, max 5, run
|
|
312
310
|
`maxConcurrent` at a time) that writes a test asserting the CORRECT behaviour,
|
|
313
311
|
runs it in the worktree, and captures it failing because of the bug. The proof rides on the finding as
|
|
314
|
-
`proof: {attempted, proven, reason, testCode?, testCommand?, redOutput?}`.
|
|
312
|
+
`proof: {attempted, proven, outcome, reason, testCode?, testCommand?, redOutput?}`.
|
|
315
313
|
A proof that comes back GREEN (code behaved correctly) is counter-evidence -
|
|
316
|
-
|
|
314
|
+
the workflow automatically downgrades the finding from Critical to Important.
|
|
317
315
|
Hard-rule findings are never proved (policy violations have no failing test).
|
|
318
316
|
|
|
319
317
|
Findings have schema:
|
|
320
|
-
`{file, line, severity, title, description, badCode, fix, rule?, precedent?, agreedBy?, verifierReasoning?, proof?}`
|
|
318
|
+
`{file, line, severity, title, description, badCode, fix, rule?, precedent?, agreedBy?, verificationStatus?, verifierReasoning?, proof?}`
|
|
321
319
|
`badCode` and `fix` are schema-required: an empty string is allowed only on
|
|
322
320
|
`observation` / `idiomatic` findings.
|
|
323
321
|
|
|
@@ -326,7 +324,7 @@ provers on `sonnet`, housekeeping on `haiku`. Only the synthesis in Step 3 runs
|
|
|
326
324
|
on the session model.
|
|
327
325
|
|
|
328
326
|
Return value from the workflow:
|
|
329
|
-
`{findings, droppedCount, downgradedCount, hardRuleCount, proveAttemptCount, provenCount, agentCount, outputTokens, turnTokensTotal}`
|
|
327
|
+
`{findings, droppedCount, downgradedCount, hardRuleCount, proveAttemptCount, provenCount, acCoverage, coverageVerdict, mutationSlip, mockSmells, agentCount, outputTokens, turnTokensTotal}`
|
|
330
328
|
`outputTokens` is this workflow's own output spend; `turnTokensTotal` is the
|
|
331
329
|
whole turn's shared pool (main loop included).
|
|
332
330
|
|
|
@@ -411,7 +409,7 @@ requirements:
|
|
|
411
409
|
- When `PREV_SHA` is set: include `## 🔁 Since last review` comparing
|
|
412
410
|
`PREV_REVIEW_FILE` findings against the new head - list each as fixed or
|
|
413
411
|
still open, before any new findings.
|
|
414
|
-
- Test Quality section: populate from the
|
|
412
|
+
- Test Quality section: populate from the workflow return fields
|
|
415
413
|
(`coverageVerdict`, `mutationSlip`, `mockSmells`).
|
|
416
414
|
- Idiomatic section: populated from severity=idiomatic findings only.
|
|
417
415
|
- **💰 Review Cost block:** `outputTokens` from the workflow return is the
|
package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/implementation.md
CHANGED
|
@@ -8,6 +8,7 @@ Axes to cover:
|
|
|
8
8
|
- Business Logic / AC coverage: for each AC in the list below, mark
|
|
9
9
|
✅ met / ⚠️ partial / ❌ missing. Scope creep is also worth flagging.
|
|
10
10
|
AC_LIST: read key "acList" from CONTEXT_FILE.
|
|
11
|
+
Return the complete status summary in the structured `acCoverage` field.
|
|
11
12
|
- Scalability: N+1 queries, missing pagination, unbounded in-memory
|
|
12
13
|
collections, missing rate-limit handling, cron jobs without overlap guard,
|
|
13
14
|
missing DB indexes for new query patterns.
|
|
@@ -23,7 +24,7 @@ Axes to cover:
|
|
|
23
24
|
Set `rule: "GQL-1"` on any Critical finding raised under this axis.
|
|
24
25
|
|
|
25
26
|
Setting rule tags the finding as a house hard rule: it keeps its Critical
|
|
26
|
-
severity and skips
|
|
27
|
+
severity only after rule-specific validation and skips runtime challenges. Only set it for a genuine GQL-1
|
|
27
28
|
violation: never to shield an ordinary finding from verification.
|
|
28
29
|
|
|
29
30
|
CI_STATUS: read key "ciStatus" from the JSON file CONTEXT_FILE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# prover -- lekker-review agent prompt
|
|
2
2
|
# Receives: one FINDING as JSON, WORKTREE_PATH path, DIFF_FILE path, CONTEXT_FILE path
|
|
3
|
-
# Returns: PROOF_SCHEMA { attempted: boolean, proven: boolean, reason: string, testCode?: string, testCommand?: string, redOutput?: string }
|
|
3
|
+
# Returns: PROOF_SCHEMA { attempted: boolean, proven: boolean, outcome: 'proven'|'passed'|'inconclusive'|'not_attempted', reason: string, testCode?: string, testCommand?: string, redOutput?: string }
|
|
4
4
|
|
|
5
5
|
## Mission
|
|
6
6
|
|
|
@@ -29,8 +29,9 @@ explicitly.
|
|
|
29
29
|
## Step 1 -- Testability gate
|
|
30
30
|
|
|
31
31
|
Read the FINDING, the real code at `file:line` in `WORKTREE_PATH`, and the diff
|
|
32
|
-
context in `DIFF_FILE`. Return `attempted: false
|
|
33
|
-
`reason` when any of these
|
|
32
|
+
context in `DIFF_FILE`. Return `attempted: false, proven: false,
|
|
33
|
+
outcome: "not_attempted"` with an honest one-sentence `reason` when any of these
|
|
34
|
+
hold:
|
|
34
35
|
|
|
35
36
|
- The failure path requires live IO (Shopify/BC/Salesforce API, a real DB, the
|
|
36
37
|
network) and the repo has no test infra to fake it cheaply.
|
|
@@ -77,25 +78,26 @@ Exactly one run command, scoped to your file only:
|
|
|
77
78
|
Set the Bash tool's `timeout` parameter to 120000 for this call.
|
|
78
79
|
|
|
79
80
|
If the runner hangs or the environment fails (missing config, transform
|
|
80
|
-
errors), that is `attempted: true, proven: false
|
|
81
|
-
honestly -- never retry more than once for a pure
|
|
82
|
-
wrong config flag), and never loop.
|
|
81
|
+
errors), that is `attempted: true, proven: false, outcome: "inconclusive"`
|
|
82
|
+
with the reason. Report honestly -- never retry more than once for a pure
|
|
83
|
+
environment issue (e.g. a wrong config flag), and never loop.
|
|
83
84
|
|
|
84
85
|
---
|
|
85
86
|
|
|
86
87
|
## Step 4 -- Judge the outcome
|
|
87
88
|
|
|
88
89
|
- **Test FAILS, and the mismatch matches what the finding predicts** ->
|
|
89
|
-
`proven: true`. `redOutput` = the failure excerpt, trimmed to the
|
|
90
|
+
`proven: true, outcome: "proven"`. `redOutput` = the failure excerpt, trimmed to the
|
|
90
91
|
informative ~15 lines (expected vs received + the failing assertion line).
|
|
91
92
|
`testCode` = the full test file content. `testCommand` = the exact command
|
|
92
93
|
you ran.
|
|
93
|
-
- **Test PASSES** -> the finding did not reproduce. `proven: false
|
|
94
|
+
- **Test PASSES** -> the finding did not reproduce. `proven: false,
|
|
95
|
+
outcome: "passed"`, and
|
|
94
96
|
`reason` states plainly that the code behaved correctly for the tested
|
|
95
97
|
input. This is important review signal, not a failure of yours. Do NOT alter
|
|
96
98
|
the test to force a failure.
|
|
97
99
|
- **Test fails for an unrelated reason** (import error, env issue) ->
|
|
98
|
-
`proven: false`, honest `reason`.
|
|
100
|
+
`proven: false, outcome: "inconclusive"`, honest `reason`.
|
|
99
101
|
|
|
100
102
|
---
|
|
101
103
|
|
|
@@ -124,6 +126,7 @@ Return EXACTLY one JSON object matching PROOF_SCHEMA:
|
|
|
124
126
|
{
|
|
125
127
|
"attempted": true | false,
|
|
126
128
|
"proven": true | false,
|
|
129
|
+
"outcome": "proven" | "passed" | "inconclusive" | "not_attempted",
|
|
127
130
|
"reason": "<one or two sentences: why not attempted, why it proved, or why it didn't reproduce>",
|
|
128
131
|
"testCode": "<full test file content -- only when attempted>",
|
|
129
132
|
"testCommand": "<exact command run -- only when attempted>",
|
|
@@ -131,5 +134,5 @@ Return EXACTLY one JSON object matching PROOF_SCHEMA:
|
|
|
131
134
|
}
|
|
132
135
|
```
|
|
133
136
|
|
|
134
|
-
`attempted: false` implies `proven: false` and omits `testCode`/`testCommand`/
|
|
137
|
+
`attempted: false` implies `proven: false, outcome: "not_attempted"` and omits `testCode`/`testCommand`/
|
|
135
138
|
`redOutput`. Do not narrate outside the object.
|
|
@@ -56,7 +56,7 @@ Axes to cover:
|
|
|
56
56
|
or a `node_modules` path.
|
|
57
57
|
|
|
58
58
|
Setting rule tags the finding as a house hard rule: it keeps its Critical
|
|
59
|
-
severity and skips
|
|
59
|
+
severity only after rule-specific validation and skips runtime challenges. Only set it for a genuine
|
|
60
60
|
TS-1/TS-2 violation: never to shield an ordinary finding from verification.
|
|
61
61
|
|
|
62
62
|
CI_STATUS: read key "ciStatus" from the JSON file CONTEXT_FILE.
|
package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/test-quality.md
CHANGED
|
@@ -141,6 +141,13 @@ criticism without a fix is incomplete.
|
|
|
141
141
|
Report the mutation-slip analysis as a single paragraph under a
|
|
142
142
|
"**Mutation-slip risk:**" heading, not as line items.
|
|
143
143
|
|
|
144
|
+
Return the review summary through these structured fields in addition to
|
|
145
|
+
`findings`:
|
|
146
|
+
- `coverageVerdict`: one concise overall coverage verdict.
|
|
147
|
+
- `mutationSlip`: the mutation-slip risk paragraph.
|
|
148
|
+
- `mockSmells`: every mock-smell issue as `{file, line, description, fix}`.
|
|
149
|
+
Return an empty array when there are no mock smells.
|
|
150
|
+
|
|
144
151
|
EXISTING_REVIEWS: read key "existingReviews" from CONTEXT_FILE (awareness only, skip findings already raised)
|
|
145
152
|
|
|
146
153
|
PROJECT_RULES to verify: read key "projectRules" from CONTEXT_FILE.
|
package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/triage-quality.md
CHANGED
|
@@ -20,7 +20,7 @@ Axes to cover (Critical/Important only):
|
|
|
20
20
|
set `rule: "GQL-1"` when Critical
|
|
21
21
|
|
|
22
22
|
Setting rule tags the finding as a house hard rule: it keeps its Critical
|
|
23
|
-
severity and skips
|
|
23
|
+
severity only after rule-specific validation and skips runtime challenges. Only set it for a genuine
|
|
24
24
|
TS-1/TS-2/GQL-1 violation: never to shield an ordinary finding from
|
|
25
25
|
verification.
|
|
26
26
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# verifier -- lekker-review agent prompt
|
|
2
|
-
# Receives: one FINDING as JSON, DIFF_FILE path, CONTEXT_FILE path, WORKTREE_PATH path
|
|
2
|
+
# Receives: one FINDING as JSON, DIFF_FILE path, CONTEXT_FILE path, WORKTREE_PATH path, HOUSE_RULES_FILE path
|
|
3
3
|
# Returns: VERDICT_SCHEMA { verdict: 'confirmed'|'downgraded'|'dropped', newSeverity?, reasoning }
|
|
4
4
|
|
|
5
5
|
## Mindset
|
|
@@ -18,17 +18,19 @@ verified yourself are not confirmed findings.
|
|
|
18
18
|
|
|
19
19
|
You have received one candidate finding as JSON (field `FINDING` in your task
|
|
20
20
|
message). Run all applicable verification checks below against the finding using
|
|
21
|
-
`DIFF_FILE`, `CONTEXT_FILE`, and `
|
|
21
|
+
`DIFF_FILE`, `CONTEXT_FILE`, `WORKTREE_PATH`, and `HOUSE_RULES_FILE` (read from
|
|
22
|
+
the task message).
|
|
22
23
|
|
|
23
24
|
When in doubt, drop. A Critical must pass ALL FIVE challenges to remain Critical
|
|
24
|
-
|
|
25
|
+
unless Step 0 validates it through the house hard-rule path.
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
28
|
-
## Step 0 -- Hard-rule
|
|
29
|
+
## Step 0 -- Hard-rule validation (check this FIRST)
|
|
29
30
|
|
|
30
|
-
If the FINDING JSON has
|
|
31
|
-
`PR-1`, do NOT run the five adversarial
|
|
31
|
+
If the FINDING JSON has any non-empty `rule` field, including built-in tags
|
|
32
|
+
such as `TS-1`, `TS-2`, `GQL-1`, or `PR-1`, do NOT run the five adversarial
|
|
33
|
+
challenges below. They ask
|
|
32
34
|
runtime-failure questions that a standards violation can never answer, and
|
|
33
35
|
answering them honestly would drop a finding that house-rules policy declares
|
|
34
36
|
Critical on standards grounds rather than on runtime behaviour.
|
|
@@ -41,8 +43,9 @@ Instead run exactly two checks:
|
|
|
41
43
|
```bash
|
|
42
44
|
grep "^+" "$DIFF_FILE" | grep "<snippet>"
|
|
43
45
|
```
|
|
44
|
-
2. **Rule applicability**: the
|
|
45
|
-
|
|
46
|
+
2. **Rule applicability**: read the exact `HOUSE_RULES_FILE` path from the task
|
|
47
|
+
message, then confirm the code really violates the rule as written there --
|
|
48
|
+
e.g. an `as const` is not a type cast in
|
|
46
49
|
the TS-1 sense; a `nodes` query that legitimately fetches a single known
|
|
47
50
|
node with a documented comment may satisfy GQL-1; a `.js` file inside a
|
|
48
51
|
Liquid theme repo is exempt from TS-2.
|
|
@@ -253,7 +256,7 @@ the inference is the crux of the claim
|
|
|
253
256
|
## Outcome rules
|
|
254
257
|
|
|
255
258
|
The one exception to "a Critical must pass ALL FIVE challenges" is the
|
|
256
|
-
hard-rule path in Step 0: a `rule`-tagged finding is
|
|
259
|
+
hard-rule path in Step 0: a `rule`-tagged finding is validated solely on the
|
|
257
260
|
anchor + rule-applicability checks and never runs the five challenges.
|
|
258
261
|
|
|
259
262
|
A Critical finding must pass ALL FIVE challenges. Any failure downgrades:
|
|
@@ -18,7 +18,7 @@ All of the following are already in hand after Step 3 of SKILL.md:
|
|
|
18
18
|
- `findings.json` path (scratchpad) -- each finding carries: `file`, `line`,
|
|
19
19
|
`severity`, `title`, `description`, `badCode`, `fix`, `rule?`, `precedent?`,
|
|
20
20
|
`agreedBy?`, `verifierReasoning?`, `proof?` (proof = `{attempted, proven,
|
|
21
|
-
reason, testCode?, testCommand?, redOutput?}`).
|
|
21
|
+
outcome, reason, testCode?, testCommand?, redOutput?}`).
|
|
22
22
|
- The saved review file path: `~/code-reviews/YYYY-MM-DD-pr-N-repo.md`.
|
|
23
23
|
- PR metadata: `REPO_SLUG`, `PR_NUMBER`, `PR_URL`, title, author, `headRefName`
|
|
24
24
|
→ `baseRefName`, head sha, depth, verdict, `isDraft`, `mergeStateStatus`, CI
|
|
@@ -96,6 +96,11 @@ Hard requirements for the HTML page:
|
|
|
96
96
|
`<pre>`, a one-line explanation that the test asserts correct behavior, and
|
|
97
97
|
`testCode` collapsed behind its own `<details>`. This is the page's
|
|
98
98
|
centerpiece -- make it prominent (e.g. a red left border) but not garish.
|
|
99
|
+
When `proof.outcome === 'passed'`, render a distinct
|
|
100
|
+
"COUNTER-EVIDENCE -- focused proof test passed" panel with `reason`,
|
|
101
|
+
`testCommand`, and `testCode` collapsed behind its own `<details>`. Explain
|
|
102
|
+
that the workflow downgraded the finding to Important; do not present the
|
|
103
|
+
passing input as proof that every related input is safe.
|
|
99
104
|
- **Test Quality + Review Cost sections**, mirrored from the review file,
|
|
100
105
|
kept concise (verdict + gaps + cost table; no need to reproduce every
|
|
101
106
|
sentence).
|
|
@@ -217,7 +217,7 @@ if empty.)*
|
|
|
217
217
|
Depth: <⚡ scan | 🔍 medium | 🔬 deep>
|
|
218
218
|
Diff size: ~<N> lines (~<N> tokens)
|
|
219
219
|
Agents run: <N total>: <breakdown, e.g. "5 reviewers (sonnet) + 6 verifiers (sonnet) + 2 provers (sonnet) + 1 critic (sonnet)">
|
|
220
|
-
|
|
220
|
+
Rule checks: <N> hard-rule finding(s) validated with rule-specific checks (omit the line when 0)
|
|
221
221
|
Context sources: <the subset of issue-tracker / chat / docs / framework-docs / monitoring / CI / prior-review-memory actually used>
|
|
222
222
|
|
|
223
223
|
Output tokens: <N> ← ACTUAL workflow spend, from the workflow's outputTokens return value
|
|
@@ -253,10 +253,7 @@ Reviewer agents, verifiers, provers, and the critic all run on sonnet; triage an
|
|
|
253
253
|
self-contained but silently breaks callers.
|
|
254
254
|
- Blank line between findings. No double blank lines.
|
|
255
255
|
- No trailing whitespace, no HTML tags, no ANSI escapes.
|
|
256
|
-
- **Proof counter-evidence rule**: when `proof.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
(e.g. the tested input wasn't the one that actually breaks). A finding whose
|
|
261
|
-
proof came back green cannot silently stay Critical. When `attempted` is
|
|
262
|
-
false, say nothing: untestable is not evidence either way.
|
|
256
|
+
- **Proof counter-evidence rule**: when `proof.outcome` is `passed`, the
|
|
257
|
+
workflow has already downgraded the finding from Critical to Important.
|
|
258
|
+
Explain the passing proof in the finding body. When `attempted` is false,
|
|
259
|
+
say nothing: untestable is not evidence either way.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Zero-agent regression test for lekker-review's PURE logic.
|
|
3
|
+
//
|
|
4
|
+
// Why this exists: every defect found in the 2026-08-31 hardening pass was in
|
|
5
|
+
// pure, synchronous code - the dedup bucket key, the hard-rule exemption gate,
|
|
6
|
+
// the model/effort routing - yet the only way to exercise any of it was a live
|
|
7
|
+
// workflow run costing ~7 agents and 70+ seconds. This runs the same logic in
|
|
8
|
+
// milliseconds with no agents at all. Run it after ANY edit to workflow.js:
|
|
9
|
+
//
|
|
10
|
+
// node ~/.claude/skills/lekker-review/scripts/selftest.mjs
|
|
11
|
+
//
|
|
12
|
+
// It lifts the real functions out of workflow.js by source extraction rather
|
|
13
|
+
// than importing, because workflow.js is written for the Workflow harness (top
|
|
14
|
+
// level `return`, an injected `args` global) and is not importable as a module.
|
|
15
|
+
import { readFileSync } from 'node:fs'
|
|
16
|
+
import { fileURLToPath } from 'node:url'
|
|
17
|
+
import { dirname, join } from 'node:path'
|
|
18
|
+
|
|
19
|
+
const SKILL = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
20
|
+
// Optional arg: a different workflow.js to test. Used to prove this suite
|
|
21
|
+
// actually discriminates - point it at a pre-fix backup and it must FAIL.
|
|
22
|
+
const target = process.argv[2] || join(SKILL, 'workflow.js')
|
|
23
|
+
const src = readFileSync(target, 'utf8')
|
|
24
|
+
console.log(`selftest target: ${target}`)
|
|
25
|
+
|
|
26
|
+
function lift(name) {
|
|
27
|
+
const i = src.indexOf(`function ${name}`)
|
|
28
|
+
if (i === -1) throw new Error(`selftest: function ${name} not found in workflow.js - was it renamed?`)
|
|
29
|
+
let d = 0, j = i
|
|
30
|
+
for (;; j++) {
|
|
31
|
+
if (src[j] === '{') d++
|
|
32
|
+
else if (src[j] === '}') { d--; if (d === 0) break }
|
|
33
|
+
}
|
|
34
|
+
return src.slice(i, j + 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function liftConst(name) {
|
|
38
|
+
const m = new RegExp(`^const ${name} = .*$`, 'm').exec(src)
|
|
39
|
+
if (!m) throw new Error(`selftest: const ${name} not found in workflow.js`)
|
|
40
|
+
return m[0]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const preamble = [
|
|
44
|
+
liftConst('HARD_RULES'),
|
|
45
|
+
(() => { try { return liftConst('SAME_ISSUE_LINE_WINDOW') } catch { return 'const SAME_ISSUE_LINE_WINDOW = 30' } })(),
|
|
46
|
+
"const SEVERITY_RANK = { observation: 0, idiomatic: 1, important: 2, critical: 3 }",
|
|
47
|
+
...['titleTokens', 'sameIssue', 'nearbyLines', 'spanWithinWindow', 'hardRuleCorroborated',
|
|
48
|
+
'isHardRule', 'longest', 'mergeFindings', 'dedup', 'shouldVerify'].map(n => {
|
|
49
|
+
try { return lift(n) } catch { return `function ${n}() { throw new Error('${n} absent from this workflow.js') }` }
|
|
50
|
+
}),
|
|
51
|
+
].join('\n')
|
|
52
|
+
|
|
53
|
+
const { dedup, isHardRule, shouldVerify, sameIssue } =
|
|
54
|
+
new Function(preamble + '\nreturn { dedup, isHardRule, shouldVerify, sameIssue }')()
|
|
55
|
+
|
|
56
|
+
let failed = 0
|
|
57
|
+
function check(name, actual, expected) {
|
|
58
|
+
const a = JSON.stringify(actual), e = JSON.stringify(expected)
|
|
59
|
+
if (a === e) { console.log(` ok ${name}`) }
|
|
60
|
+
else { console.log(` FAIL ${name}\n expected ${e}\n actual ${a}`); failed++ }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log('\ndedup: the same defect anchored at different lines must merge')
|
|
64
|
+
// Regression: bucketing on `file:line` meant these two were never compared,
|
|
65
|
+
// despite a title similarity of 0.64 against a 0.4 threshold. Observed live.
|
|
66
|
+
const dupes = [
|
|
67
|
+
{ file: 'src/total.ts', line: 14, severity: 'critical', title: 'Off-by-one loop skips the first cart line', badCode: 'for (let i = 1;', description: 'aaa' },
|
|
68
|
+
{ file: 'src/total.ts', line: 9, severity: 'critical', title: 'cartTotal skips the first line item (off-by-one loop start)', badCode: 'for (let i = 1;', description: 'bb' },
|
|
69
|
+
]
|
|
70
|
+
check('two anchors, one issue -> 1 finding', dedup(dupes).length, 1)
|
|
71
|
+
check('merge keeps the highest severity', dedup([
|
|
72
|
+
{ file: 'a.ts', line: 3, severity: 'observation', title: 'Off-by-one loop skips first line', badCode: '', description: '' },
|
|
73
|
+
{ file: 'a.ts', line: 5, severity: 'critical', title: 'Off-by-one loop skips the first line', badCode: '', description: '' },
|
|
74
|
+
])[0].severity, 'critical')
|
|
75
|
+
|
|
76
|
+
console.log('\ndedup: distinct issues must NOT be merged')
|
|
77
|
+
check('similar titles 390 lines apart stay separate', dedup([
|
|
78
|
+
{ file: 'big.ts', line: 10, severity: 'important', title: 'Missing pagination on the products query', badCode: '', description: '' },
|
|
79
|
+
{ file: 'big.ts', line: 400, severity: 'important', title: 'Missing pagination on the orders query', badCode: '', description: '' },
|
|
80
|
+
]).length, 2)
|
|
81
|
+
check('same line, unrelated titles stay separate', dedup([
|
|
82
|
+
{ file: 'a.ts', line: 7, severity: 'important', title: 'Unbounded retry loop hides throttling', badCode: '', description: '' },
|
|
83
|
+
{ file: 'a.ts', line: 7, severity: 'important', title: 'Metafield namespace hardcoded in the query', badCode: '', description: '' },
|
|
84
|
+
]).length, 2)
|
|
85
|
+
// Grouping must not depend on arrival order. With only g[0] compared, findings
|
|
86
|
+
// at 25, 50 and 1 all joined when 25 arrived first, spanning 49 lines.
|
|
87
|
+
const spanCase = [
|
|
88
|
+
{ file: 'a.ts', line: 25, severity: 'important', title: 'Missing pagination on the query', badCode: '', description: '' },
|
|
89
|
+
{ file: 'a.ts', line: 50, severity: 'important', title: 'Missing pagination on the query', badCode: '', description: '' },
|
|
90
|
+
{ file: 'a.ts', line: 1, severity: 'important', title: 'Missing pagination on the query', badCode: '', description: '' },
|
|
91
|
+
]
|
|
92
|
+
check('a group never spans more than the window (25, 50, 1)', dedup(spanCase).length, 2)
|
|
93
|
+
check('the same set in a different order gives the same answer',
|
|
94
|
+
dedup([spanCase[2], spanCase[0], spanCase[1]]).length, dedup(spanCase).length)
|
|
95
|
+
|
|
96
|
+
check('different files never merge', dedup([
|
|
97
|
+
{ file: 'a.ts', line: 7, severity: 'critical', title: 'Off-by-one loop skips the first line', badCode: '', description: '' },
|
|
98
|
+
{ file: 'b.ts', line: 7, severity: 'critical', title: 'Off-by-one loop skips the first line', badCode: '', description: '' },
|
|
99
|
+
]).length, 2)
|
|
100
|
+
|
|
101
|
+
console.log('\nhard rules: a tag must be corroborated to skip verification')
|
|
102
|
+
// Regression: any agent could bypass the verifier by writing rule: "TS-1".
|
|
103
|
+
// Observed live - a test-coverage finding and a comment-policy finding both did.
|
|
104
|
+
check('TS-1 on a comment-policy finding is NOT exempt',
|
|
105
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 6, title: 'Comment restates the function', badCode: '/** Sum a cart. */', description: 'a comment earns its place' }), false)
|
|
106
|
+
check('TS-1 on a test-coverage finding is NOT exempt',
|
|
107
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 8, title: 'No test coverage', badCode: 'for (let i = 1;', description: 'zero test files added' }), false)
|
|
108
|
+
check('an unknown rule string is NOT exempt',
|
|
109
|
+
isHardRule({ rule: 'MADE-UP', file: 'a.ts', line: 1, title: 't', badCode: 'x as Foo', description: '' }), false)
|
|
110
|
+
// TS-1 is judged on quoted code only: prose is full of `as` and `any`.
|
|
111
|
+
check('the word "any" in PROSE alone is NOT exempt',
|
|
112
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'fails on any cart with items', badCode: 'total += lines[i].price', description: 'any agent could trip this' }), false)
|
|
113
|
+
check('the phrase "such as" in prose alone is NOT exempt',
|
|
114
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'issue', badCode: 'const n = 1', description: 'a primitive such as String is used' }), false)
|
|
115
|
+
|
|
116
|
+
console.log('\nhard rules: genuine violations must STILL be exempt')
|
|
117
|
+
check('TS-1 with a real cast', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: 'const x = y as Foo;', description: '' }), true)
|
|
118
|
+
check('TS-1 with a real any', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
|
|
119
|
+
check('TS-2 with a .js path', isHardRule({ rule: 'TS-2', file: 'web/thing.js', line: 1, title: 'js added', badCode: '', description: '' }), true)
|
|
120
|
+
check('GQL-1 with a nodes query',isHardRule({ rule: 'GQL-1', file: 'q.graphql', line: 1, title: 'no pageInfo', badCode: 'products { nodes { id } }', description: '' }), true)
|
|
121
|
+
check('PR-1 anchored on the PR title', isHardRule({ rule: 'PR-1', file: 'PR title', line: 1, title: 'missing prefix', badCode: '', description: '' }), true)
|
|
122
|
+
// A cast to a lowercase built-in is as much a TS-1 violation as a cast to a
|
|
123
|
+
// named type. Missing it sent a genuine hard rule to a verifier that cannot
|
|
124
|
+
// answer a policy claim, where it could be dropped.
|
|
125
|
+
for (const cast of ['x as string', 'x as number', 'x as unknown as Foo', 'x as const', 'x as boolean']) {
|
|
126
|
+
check(`TS-1 corroborated by \`${cast}\``,
|
|
127
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: cast, description: '' }), true)
|
|
128
|
+
}
|
|
129
|
+
check('TS-1 corroborated by an any annotation',
|
|
130
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
|
|
131
|
+
check('TS-1 corroborated by an any[] ',
|
|
132
|
+
isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'const xs: any[] = []', description: '' }), true)
|
|
133
|
+
|
|
134
|
+
console.log('\nverification scope by depth')
|
|
135
|
+
const crit = { severity: 'critical' }, imp = { severity: 'important' }, obs = { severity: 'observation' }
|
|
136
|
+
check('scan verifies nothing', [crit, imp, obs].map(f => shouldVerify(f, 'scan')), [false, false, false])
|
|
137
|
+
check('medium verifies criticals only', [crit, imp, obs].map(f => shouldVerify(f, 'medium')), [true, false, false])
|
|
138
|
+
check('deep verifies crit + important', [crit, imp, obs].map(f => shouldVerify(f, 'deep')), [true, true, false])
|
|
139
|
+
check('a corroborated hard rule is never verified',
|
|
140
|
+
shouldVerify({ severity: 'critical', rule: 'TS-2', file: 'x.js', badCode: '', description: '', title: '' }, 'deep'), false)
|
|
141
|
+
|
|
142
|
+
// Per-host model routing is optional: a deployment may pin models per host via
|
|
143
|
+
// a MODEL_TABLE, or leave every agent() call to name its own model. Test it
|
|
144
|
+
// only when it is present, so this suite runs against either shape.
|
|
145
|
+
const routingAssign = /const\s+MODEL\s*=\s*MODEL_TABLE\s*\[\s*HOST\s*\]/.exec(src)
|
|
146
|
+
const hasRouting = Boolean(routingAssign)
|
|
147
|
+
// A guard that can silently disable itself is worse than no guard. If the file
|
|
148
|
+
// clearly HAS a MODEL_TABLE but the assignment did not parse, that is a failure,
|
|
149
|
+
// not a reason to skip.
|
|
150
|
+
if (!hasRouting && /MODEL_TABLE/.test(src)) {
|
|
151
|
+
check('MODEL_TABLE is present but its assignment was not recognised', false, true)
|
|
152
|
+
}
|
|
153
|
+
if (!hasRouting) {
|
|
154
|
+
console.log('\nmodel + effort routing: not configured in this workflow.js, skipped')
|
|
155
|
+
} else {
|
|
156
|
+
console.log('\nmodel + effort routing is pinned per host, never inherited')
|
|
157
|
+
const routing = new Function('input', [
|
|
158
|
+
src.slice(src.indexOf('const HOST = '), routingAssign.index + routingAssign[0].length),
|
|
159
|
+
'return { HOST, MODEL }',
|
|
160
|
+
].join('\n'))
|
|
161
|
+
check('an absent host arg falls back to the default table', routing({}).MODEL, routing({ host: 'claude' }).MODEL)
|
|
162
|
+
check('an unknown host falls back to the default, not an invalid model', routing({ host: 'nonsense' }).HOST, 'claude')
|
|
163
|
+
check('host matching is case-insensitive', routing({ host: 'CODEX' }).HOST, 'codex')
|
|
164
|
+
// Every role must resolve to a non-empty model, and effort must be set.
|
|
165
|
+
for (const host of ['claude', 'codex']) {
|
|
166
|
+
const m = routing({ host }).MODEL
|
|
167
|
+
const roles = Object.keys(m).filter(k => k !== 'effort')
|
|
168
|
+
check(`${host}: every role resolves to a model`, roles.every(r => typeof m[r] === 'string' && m[r].length > 0), true)
|
|
169
|
+
check(`${host}: effort is set`, typeof m.effort === 'string' && m.effort.length > 0, true)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log(failed === 0 ? '\nall checks passed\n' : `\n${failed} check(s) FAILED\n`)
|
|
174
|
+
process.exit(failed === 0 ? 0 : 1)
|
|
@@ -11,6 +11,9 @@ import { readFileSync } from 'node:fs';
|
|
|
11
11
|
const THRESHOLD = 1500;
|
|
12
12
|
const OFFER_MARKER = /critical-thinking review/i; // the offer line must contain this; doubles as a loop guard
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Exits the hook cleanly when conditions for offering a critique are not met.
|
|
16
|
+
*/
|
|
14
17
|
function bail() { process.exit(0); } // any uncertainty => do nothing, never block the user
|
|
15
18
|
|
|
16
19
|
let raw = '';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: open-source-publisher
|
|
3
|
-
description: Prepare an open-source repository for polished public publishing. Use when a user asks to publish, open-source, launch, polish, package, brand, or make a GitHub project presentable with a minimal project icon, social preview image, GitHub Pages landing page, standardized README, essential shields, CI/CD quality gates, release automation checks, and optional donation setup. Prefer the external `logo-generator` skill for icon generation when available, and `nolangz/pixel2motion` for optional motion previews of
|
|
3
|
+
description: Prepare an open-source repository for polished public publishing. Use when a user asks to publish, open-source, launch, polish, package, brand, or make a GitHub project presentable with a minimal project icon, social preview image, GitHub Pages landing page, standardized README, essential shields, CI/CD quality gates, release automation checks, and optional donation setup. Prefer the external `logo-generator` skill for icon generation when available, and `nolangz/pixel2motion` for optional motion previews of supported logos or simple artwork.
|
|
4
4
|
license: MIT
|
|
5
5
|
allowed-tools: Bash, Read, Write, Edit, WebSearch, WebFetch
|
|
6
6
|
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires a writable git repository; browser or image rendering tools are useful for visual validation.
|
|
@@ -44,12 +44,11 @@ Use this skill to audit whether an OSS repository is ready to publish, then help
|
|
|
44
44
|
5. For existing usable pieces, do not propose replacement by default. Ask a change-oriented question only when useful, for example:
|
|
45
45
|
- "You already have a terminal-style GitHub Pages site. Do you want to keep it or restyle it?"
|
|
46
46
|
- "You already have an icon and social card. Do you want a refresh, or should I leave them as-is?"
|
|
47
|
-
- "You already have a static social card. Do you want me to animate it with pixel2motion, or leave it static?"
|
|
48
47
|
- "You already have release automation. Do you want me to audit only, or also tighten it?"
|
|
49
48
|
6. Ask only for choices needed to fix missing or weak pieces:
|
|
50
49
|
- If GitHub Pages is missing or weak, ask for style: `oldschool linux`, `terminal`, `modern`, `brutalist`, `glassmorphism`, `y2k`, `hacker`, or custom.
|
|
51
50
|
- If donation wiring is missing, ask whether to enable it: `none`, `GitHub Sponsors`, `Ko-fi`, `Buy Me a Coffee`, `Open Collective`, `Thanks.dev`, or custom URL.
|
|
52
|
-
- If the repo has a generated
|
|
51
|
+
- If the repo has a generated logo or simple hero artwork supported by `nolangz/pixel2motion`, ask whether to animate it or leave it static.
|
|
53
52
|
- If the repo has no clear product essence, ask for a one-sentence positioning statement.
|
|
54
53
|
7. Implement only approved, missing, or weak work in this order:
|
|
55
54
|
- OSS governance and support files
|
|
@@ -213,8 +212,8 @@ Use `magick` or another renderer when `rsvg-convert` is unavailable.
|
|
|
213
212
|
|
|
214
213
|
Some repos benefit from a short animated preview. Keep this opt-in.
|
|
215
214
|
|
|
216
|
-
-
|
|
217
|
-
-
|
|
215
|
+
- After the user opts in during workflow step 6, animate only the approved generated logo or simple artwork.
|
|
216
|
+
- Use `nolangz/pixel2motion` as the optional dependency for that animation, animated HTML demos, and GIF/video previews.
|
|
218
217
|
- Do not auto-animate by default.
|
|
219
218
|
|
|
220
219
|
## README Standard
|
|
@@ -11,6 +11,9 @@ import { readFileSync } from 'node:fs';
|
|
|
11
11
|
const THRESHOLD = 1500;
|
|
12
12
|
const OFFER_MARKER = /critical-thinking review/i; // the offer line must contain this; doubles as a loop guard
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Exits the hook cleanly when conditions for offering a critique are not met.
|
|
16
|
+
*/
|
|
14
17
|
function bail() { process.exit(0); } // any uncertainty => do nothing, never block the user
|
|
15
18
|
|
|
16
19
|
let raw = '';
|