@olegkoval/agent-skills 1.26.0 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -1
- package/README.md +7 -3
- package/catalog/skills.json +18 -0
- package/package.json +5 -3
- package/packages/software-development/lekker-review/SKILL.md +519 -0
- package/packages/software-development/lekker-review/adapters/claude/plugin.json +5 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/SKILL.md +520 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/completeness-critic.md +21 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/conventions.md +124 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/fix-verifier.md +84 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/fixer.md +120 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/implementation.md +53 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/prover.md +135 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/quality.md +72 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/simplification.md +45 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/test-quality.md +170 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/triage-logic.md +27 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/triage-quality.md +41 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/agents/verifier.md +295 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/artifact-page.md +143 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/context-gathering.md +162 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/fix-mode.md +329 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/github-post.md +205 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/house-rules.md +76 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/references/output-format.md +232 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/scripts/changed-files.sh +77 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/scripts/setup-worktree.sh +337 -0
- package/packages/software-development/lekker-review/adapters/claude/skills/lekker-review/scripts/verify-fixes.sh +231 -0
- package/packages/software-development/lekker-review/fix-workflow.js +273 -0
- package/packages/software-development/lekker-review/references/agents/completeness-critic.md +21 -0
- package/packages/software-development/lekker-review/references/agents/conventions.md +124 -0
- package/packages/software-development/lekker-review/references/agents/fix-verifier.md +84 -0
- package/packages/software-development/lekker-review/references/agents/fixer.md +120 -0
- package/packages/software-development/lekker-review/references/agents/implementation.md +53 -0
- package/packages/software-development/lekker-review/references/agents/prover.md +135 -0
- package/packages/software-development/lekker-review/references/agents/quality.md +72 -0
- package/packages/software-development/lekker-review/references/agents/simplification.md +45 -0
- package/packages/software-development/lekker-review/references/agents/test-quality.md +170 -0
- package/packages/software-development/lekker-review/references/agents/triage-logic.md +27 -0
- package/packages/software-development/lekker-review/references/agents/triage-quality.md +41 -0
- package/packages/software-development/lekker-review/references/agents/verifier.md +295 -0
- package/packages/software-development/lekker-review/references/artifact-page.md +143 -0
- package/packages/software-development/lekker-review/references/context-gathering.md +162 -0
- package/packages/software-development/lekker-review/references/fix-mode.md +329 -0
- package/packages/software-development/lekker-review/references/github-post.md +205 -0
- package/packages/software-development/lekker-review/references/house-rules.md +76 -0
- package/packages/software-development/lekker-review/references/output-format.md +232 -0
- package/packages/software-development/lekker-review/scripts/changed-files.sh +77 -0
- package/packages/software-development/lekker-review/scripts/setup-worktree.sh +337 -0
- package/packages/software-development/lekker-review/scripts/verify-fixes.sh +231 -0
- package/packages/software-development/lekker-review/workflow.js +602 -0
- package/site/assets/paperbag.css +707 -0
- package/site/assets/paperbag.js +218 -0
- package/site/build.mjs +380 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# verify-fixes.sh -- lekker-review fix-mode helper
|
|
3
|
+
# Runs static checks + (optionally) the test suite against the worktree AFTER
|
|
4
|
+
# fix agents have edited it, and emits a JSON result file.
|
|
5
|
+
#
|
|
6
|
+
# Usage: verify-fixes.sh WORKTREE_PATH OUT_JSON [RUN_TESTS]
|
|
7
|
+
# RUN_TESTS: "tests" to run the package test script, anything else to skip.
|
|
8
|
+
#
|
|
9
|
+
# Never fails on a failing check -- a failing check is data, not an error.
|
|
10
|
+
# Exit code is non-zero only when the worktree itself is unusable.
|
|
11
|
+
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
|
|
14
|
+
WORKTREE_PATH="${1:?WORKTREE_PATH required}"
|
|
15
|
+
OUT_JSON="${2:?OUT_JSON required}"
|
|
16
|
+
RUN_TESTS="${3:-no-tests}"
|
|
17
|
+
|
|
18
|
+
if [[ ! -d "$WORKTREE_PATH/.git" ]] && [[ ! -f "$WORKTREE_PATH/.git" ]]; then
|
|
19
|
+
printf 'ERROR: %s is not a git worktree\n' "$WORKTREE_PATH" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
TSC_FILE="/tmp/lekker-fix-tsc-$$.txt"
|
|
24
|
+
TSC_FULL_FILE="/tmp/lekker-fix-tsc-full-$$.txt"
|
|
25
|
+
TSC_CHANGED_FILE="/tmp/lekker-fix-tsc-changed-$$.txt"
|
|
26
|
+
TSC_COUNT_FILE="/tmp/lekker-fix-tsc-count-$$.txt"
|
|
27
|
+
ESLINT_FILE="/tmp/lekker-fix-eslint-$$.txt"
|
|
28
|
+
ESLINT_SCOPE_FILE="/tmp/lekker-fix-eslint-scope-$$.txt"
|
|
29
|
+
TEST_FILE="/tmp/lekker-fix-test-$$.txt"
|
|
30
|
+
STAT_FILE="/tmp/lekker-fix-stat-$$.txt"
|
|
31
|
+
printf '' > "$TSC_FILE"
|
|
32
|
+
printf '' > "$TSC_CHANGED_FILE"
|
|
33
|
+
printf '0' > "$TSC_COUNT_FILE"
|
|
34
|
+
printf '' > "$ESLINT_FILE"
|
|
35
|
+
printf 'skipped' > "$ESLINT_SCOPE_FILE"
|
|
36
|
+
printf '' > "$TEST_FILE"
|
|
37
|
+
|
|
38
|
+
HAS_NM=false
|
|
39
|
+
[[ -d "$WORKTREE_PATH/node_modules" || -L "$WORKTREE_PATH/node_modules" ]] && HAS_NM=true
|
|
40
|
+
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
# Uncommitted change footprint (what the fix agents actually wrote)
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
git -C "$WORKTREE_PATH" diff --stat > "$STAT_FILE" 2>&1 || true
|
|
45
|
+
DIRTY="$(git -C "$WORKTREE_PATH" status --porcelain 2>/dev/null || true)"
|
|
46
|
+
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
# Determine changed files (to scope tsc/eslint identically to setup-worktree
|
|
49
|
+
# so fix-mode's post-fix numbers compare like-for-like against the baseline).
|
|
50
|
+
# --include-uncommitted also picks up what the fix agents just wrote, even if
|
|
51
|
+
# it wasn't part of the original PR diff.
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
CHANGED_FILES_FILE="/tmp/lekker-fix-changed-$$.txt"
|
|
54
|
+
BASE_REF_NOTE="$("$(dirname "$0")/changed-files.sh" "$WORKTREE_PATH" --include-uncommitted 2>&1 >"$CHANGED_FILES_FILE" | sed -n 's/^base-ref: //p')" || true
|
|
55
|
+
|
|
56
|
+
# A blank line here would make `grep -F -f` match EVERY tsc error line, turning
|
|
57
|
+
# the repo's standing type debt into "errors the fixes introduced". Strip them.
|
|
58
|
+
if [[ -f "$CHANGED_FILES_FILE" ]]; then
|
|
59
|
+
grep -v '^[[:space:]]*$' "$CHANGED_FILES_FILE" > "${CHANGED_FILES_FILE}.clean" 2>/dev/null || true
|
|
60
|
+
mv "${CHANGED_FILES_FILE}.clean" "$CHANGED_FILES_FILE" 2>/dev/null || true
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
BASE_REF_VAL="null"
|
|
64
|
+
if [[ -n "$BASE_REF_NOTE" ]] && [[ "$BASE_REF_NOTE" != "unknown" ]]; then
|
|
65
|
+
BASE_REF_VAL="$BASE_REF_NOTE"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Lintable, still-on-disk changed files (a deleted file must not go to eslint).
|
|
69
|
+
ESLINT_TARGETS=()
|
|
70
|
+
if [[ -s "$CHANGED_FILES_FILE" ]]; then
|
|
71
|
+
while IFS= read -r cf; do
|
|
72
|
+
[[ -z "$cf" ]] && continue
|
|
73
|
+
case "$cf" in
|
|
74
|
+
*.ts|*.tsx|*.js|*.jsx|*.mjs|*.cjs) ;;
|
|
75
|
+
*) continue ;;
|
|
76
|
+
esac
|
|
77
|
+
[[ -f "$WORKTREE_PATH/$cf" ]] || continue
|
|
78
|
+
ESLINT_TARGETS+=("$cf")
|
|
79
|
+
done < "$CHANGED_FILES_FILE"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ---------------------------------------------------------------------------
|
|
83
|
+
# tsc + eslint (concurrent)
|
|
84
|
+
# ---------------------------------------------------------------------------
|
|
85
|
+
run_tsc() {
|
|
86
|
+
# tsc needs the whole program to resolve types, so it always runs
|
|
87
|
+
# repo-wide; only the reported OUTPUT is split by changed-file scope.
|
|
88
|
+
if [[ -f "$WORKTREE_PATH/tsconfig.json" ]] && [[ "$HAS_NM" == "true" ]]; then
|
|
89
|
+
(cd "$WORKTREE_PATH" && npx tsc --noEmit) > "$TSC_FULL_FILE" 2>&1 || true
|
|
90
|
+
tail -40 "$TSC_FULL_FILE" >> "$TSC_FILE" || true
|
|
91
|
+
grep -c 'error TS' "$TSC_FULL_FILE" > "$TSC_COUNT_FILE" 2>/dev/null || printf '0' > "$TSC_COUNT_FILE"
|
|
92
|
+
if [[ -s "$CHANGED_FILES_FILE" ]]; then
|
|
93
|
+
grep -F -f "$CHANGED_FILES_FILE" "$TSC_FULL_FILE" 2>/dev/null | tail -40 > "$TSC_CHANGED_FILE" || true
|
|
94
|
+
fi
|
|
95
|
+
rm -f "$TSC_FULL_FILE"
|
|
96
|
+
else
|
|
97
|
+
printf 'skipped\n' > "$TSC_FILE"
|
|
98
|
+
printf '0' > "$TSC_COUNT_FILE"
|
|
99
|
+
fi
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
run_eslint() {
|
|
103
|
+
if [[ "$HAS_NM" != "true" ]]; then
|
|
104
|
+
printf 'skipped\n' > "$ESLINT_FILE"
|
|
105
|
+
printf 'skipped' > "$ESLINT_SCOPE_FILE"
|
|
106
|
+
return
|
|
107
|
+
fi
|
|
108
|
+
local has_config
|
|
109
|
+
has_config=false
|
|
110
|
+
(cd "$WORKTREE_PATH" && compgen -G '.eslintrc*' >/dev/null 2>&1) && has_config=true
|
|
111
|
+
if [[ "$has_config" == "false" ]]; then
|
|
112
|
+
(cd "$WORKTREE_PATH" && compgen -G 'eslint.config*' >/dev/null 2>&1) && has_config=true
|
|
113
|
+
fi
|
|
114
|
+
if [[ "$has_config" == "true" ]]; then
|
|
115
|
+
if [[ -s "$CHANGED_FILES_FILE" ]]; then
|
|
116
|
+
if [[ ${#ESLINT_TARGETS[@]} -gt 0 ]]; then
|
|
117
|
+
(cd "$WORKTREE_PATH" && npx eslint --max-warnings=0 "${ESLINT_TARGETS[@]}" 2>&1 | tail -40 >> "$ESLINT_FILE") || true
|
|
118
|
+
printf 'changed-files' > "$ESLINT_SCOPE_FILE"
|
|
119
|
+
else
|
|
120
|
+
printf 'no-changed-lintable-files\n' > "$ESLINT_FILE"
|
|
121
|
+
printf 'none' > "$ESLINT_SCOPE_FILE"
|
|
122
|
+
fi
|
|
123
|
+
else
|
|
124
|
+
# Base ref could not be resolved -- fall back to the old repo-wide run.
|
|
125
|
+
(cd "$WORKTREE_PATH" && npx eslint . --max-warnings=0 2>&1 | tail -40 >> "$ESLINT_FILE") || true
|
|
126
|
+
printf 'full-fallback' > "$ESLINT_SCOPE_FILE"
|
|
127
|
+
fi
|
|
128
|
+
else
|
|
129
|
+
printf 'no-eslint-config\n' > "$ESLINT_FILE"
|
|
130
|
+
printf 'no-eslint-config' > "$ESLINT_SCOPE_FILE"
|
|
131
|
+
fi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
run_tsc &
|
|
135
|
+
TSC_PID=$!
|
|
136
|
+
run_eslint &
|
|
137
|
+
ESLINT_PID=$!
|
|
138
|
+
wait "$TSC_PID" || true
|
|
139
|
+
wait "$ESLINT_PID" || true
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
# Test suite (sequential, opt-in, hard timeout)
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
TEST_RAN=false
|
|
145
|
+
TEST_EXIT="null"
|
|
146
|
+
if [[ "$RUN_TESTS" == "tests" ]] && [[ "$HAS_NM" == "true" ]] \
|
|
147
|
+
&& [[ -f "$WORKTREE_PATH/package.json" ]] \
|
|
148
|
+
&& grep -q '"test"[[:space:]]*:' "$WORKTREE_PATH/package.json"; then
|
|
149
|
+
TEST_RAN=true
|
|
150
|
+
# `set -o pipefail` is active, so the subshell's exit status already
|
|
151
|
+
# reflects a failing `npm test` even though tail is last in the pipeline.
|
|
152
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
153
|
+
(cd "$WORKTREE_PATH" && timeout 600 npm test --silent 2>&1 | tail -60 >> "$TEST_FILE")
|
|
154
|
+
else
|
|
155
|
+
(cd "$WORKTREE_PATH" && npm test --silent 2>&1 | tail -60 >> "$TEST_FILE")
|
|
156
|
+
fi
|
|
157
|
+
TEST_EXIT=$?
|
|
158
|
+
else
|
|
159
|
+
printf 'skipped\n' > "$TEST_FILE"
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
HEAD_SHA_SHORT="$(git -C "$WORKTREE_PATH" rev-parse --short HEAD 2>/dev/null || printf 'unknown')"
|
|
163
|
+
|
|
164
|
+
# ---------------------------------------------------------------------------
|
|
165
|
+
# Emit JSON
|
|
166
|
+
# ---------------------------------------------------------------------------
|
|
167
|
+
python3 - \
|
|
168
|
+
"$TSC_FILE" \
|
|
169
|
+
"$ESLINT_FILE" \
|
|
170
|
+
"$TEST_FILE" \
|
|
171
|
+
"$STAT_FILE" \
|
|
172
|
+
"$TEST_RAN" \
|
|
173
|
+
"$TEST_EXIT" \
|
|
174
|
+
"$HEAD_SHA_SHORT" \
|
|
175
|
+
"$DIRTY" \
|
|
176
|
+
"$CHANGED_FILES_FILE" \
|
|
177
|
+
"$BASE_REF_VAL" \
|
|
178
|
+
"$ESLINT_SCOPE_FILE" \
|
|
179
|
+
"$TSC_CHANGED_FILE" \
|
|
180
|
+
"$TSC_COUNT_FILE" \
|
|
181
|
+
"$OUT_JSON" <<'PYEOF'
|
|
182
|
+
import json, sys, os
|
|
183
|
+
|
|
184
|
+
(tsc_file, eslint_file, test_file, stat_file, test_ran, test_exit,
|
|
185
|
+
head_sha_short, dirty, changed_files_file, base_ref_val,
|
|
186
|
+
eslint_scope_file, tsc_changed_file, tsc_count_file,
|
|
187
|
+
out_json) = sys.argv[1:15]
|
|
188
|
+
|
|
189
|
+
def read_file(path):
|
|
190
|
+
if not os.path.exists(path):
|
|
191
|
+
return ""
|
|
192
|
+
with open(path, "r", errors="replace") as f:
|
|
193
|
+
return f.read()
|
|
194
|
+
|
|
195
|
+
changed_files = [l for l in read_file(changed_files_file).splitlines() if l.strip()]
|
|
196
|
+
|
|
197
|
+
eslint_scope = read_file(eslint_scope_file).strip() or "skipped"
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
tsc_error_count = int(read_file(tsc_count_file).strip() or "0")
|
|
201
|
+
except ValueError:
|
|
202
|
+
tsc_error_count = 0
|
|
203
|
+
|
|
204
|
+
data = {
|
|
205
|
+
"tscTail": read_file(tsc_file),
|
|
206
|
+
"eslintTail": read_file(eslint_file),
|
|
207
|
+
"testTail": read_file(test_file),
|
|
208
|
+
"testRan": test_ran == "true",
|
|
209
|
+
"testExitCode": None if test_exit in ("null", "") else int(test_exit),
|
|
210
|
+
"diffStat": read_file(stat_file),
|
|
211
|
+
"dirtyPaths": [l for l in dirty.splitlines() if l.strip()],
|
|
212
|
+
"headShaShort": head_sha_short,
|
|
213
|
+
"changedFiles": changed_files,
|
|
214
|
+
"baseRef": None if base_ref_val == "null" else base_ref_val,
|
|
215
|
+
"eslintScope": eslint_scope,
|
|
216
|
+
"tscChangedTail": read_file(tsc_changed_file),
|
|
217
|
+
"tscErrorCount": tsc_error_count,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
for p in (tsc_file, eslint_file, test_file, stat_file, changed_files_file,
|
|
221
|
+
eslint_scope_file, tsc_changed_file, tsc_count_file):
|
|
222
|
+
try:
|
|
223
|
+
os.remove(p)
|
|
224
|
+
except OSError:
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
with open(out_json, "w") as f:
|
|
228
|
+
json.dump(data, f, indent=2)
|
|
229
|
+
|
|
230
|
+
print("OK " + out_json)
|
|
231
|
+
PYEOF
|