@iceinvein/agent-skills 0.23.12 → 0.23.13
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/package.json +1 -1
- package/skills/index.json +1 -1
- package/skills/magpie/SKILL.md +1 -1
- package/skills/magpie/bin/magpie.ts +2 -2
- package/skills/magpie/references/proof.md +6 -3
- package/skills/magpie/scripts/__tests__/history.test.ts +28 -0
- package/skills/magpie/scripts/__tests__/proof.test.ts +9 -2
- package/skills/magpie/scripts/__tests__/skill-lint.test.ts +9 -0
- package/skills/magpie/scripts/history.ts +9 -3
- package/skills/magpie/scripts/proof.ts +3 -3
- package/skills/magpie/skill.json +1 -1
package/package.json
CHANGED
package/skills/index.json
CHANGED
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
"name": "magpie",
|
|
228
228
|
"description": "Interactive PR review pipeline. Runs five parallel specialist subagents (security, bugs, performance, code-smells, architecture) plus a once-per-PR checks pass that finds tests and controls able to pass without proving their purpose, drops findings whose quoted evidence is not in the code, dedupes, runs critic subagents that re-check each finding against the worktree and set its risk label, peer-reviews via codex exec (falling back to a Claude second opinion when codex is unavailable), and serves an interactive HTML report for selecting or dismissing findings to post via gh, recording the outcome per finding as labels. Bundles a Bun CLI put on PATH by the skill's postinstall step under a bunx install, or by the plugin's bin/ under a Claude Code plugin install. Use when the user asks to review a GitHub pull request. Local mode (setup --local) runs the same pipeline on the current branch's diff from its merge base, uncommitted and untracked work included, against the caller's live tree, with no server or posting, and hands the ranked findings back in the terminal for an implementing or orchestrating agent to address. Splits oversized diffs into budgeted shards and rebuilds the diff from the local clone when gh pr diff refuses it.",
|
|
229
229
|
"type": "prompt",
|
|
230
|
-
"version": "0.16.
|
|
230
|
+
"version": "0.16.1"
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
233
|
"name": "migrate",
|
package/skills/magpie/SKILL.md
CHANGED
|
@@ -203,7 +203,7 @@ If codex returns non-zero on a batch, do not abort: record `{stage: peer-review,
|
|
|
203
203
|
|
|
204
204
|
### 7b. Proof
|
|
205
205
|
|
|
206
|
-
Append `{stage: proof, status: running}` and re-render progress. `magpie proof-prompt "$RUN_DIR"` fills `references/proof.md` for up to 8
|
|
206
|
+
Append `{stage: proof, status: running}` and re-render progress. `magpie proof-prompt "$RUN_DIR"` fills `references/proof.md` for up to 8 must-fix or should-fix findings, printing `<prompt path>\t<output path>` each. On a PR run with any printed, first install `$WORKTREE`'s dependencies once with the repo's frozen-lockfile command (`npm ci`, `uv sync --frozen`, ...); on failure log `{stage: proof-deps, status: skipped, error}` and go on. Dispatch the prompts as stage 6 does its batches, then `magpie proof-apply "$RUN_DIR"`: it drops disproved findings to `proof-dropped.json`, marks the rest and logs `done`. On a non-zero exit, delete only the `proof-<id>.json` files or leftovers stderr names, then re-dispatch or re-apply.
|
|
207
207
|
|
|
208
208
|
### 8. Report
|
|
209
209
|
|
|
@@ -22,8 +22,8 @@ Subcommands:
|
|
|
22
22
|
critic-apply <run-dir> [--design-cap N]
|
|
23
23
|
Apply critic verdicts, write findings.kept.json (no cap on
|
|
24
24
|
code-smells + architecture keeps unless --design-cap is given)
|
|
25
|
-
proof-prompt <run-dir> Write one proof prompt per
|
|
26
|
-
output paths
|
|
25
|
+
proof-prompt <run-dir> Write one proof prompt per must-fix or should-fix finding, print
|
|
26
|
+
prompt and output paths
|
|
27
27
|
proof-apply <run-dir> Fold proof results into findings.final.json, drop the disproved
|
|
28
28
|
shard <run-dir> [--budget N] [--max-files N]
|
|
29
29
|
Re-split diff.patch into budgeted shards (and the
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Proof prompt
|
|
2
2
|
|
|
3
3
|
Stage 7b of the walkthrough does not read this file by hand. `magpie proof-prompt
|
|
4
|
-
"$RUN_DIR"` picks the findings worth proving from `findings.final.json` (
|
|
5
|
-
|
|
4
|
+
"$RUN_DIR"` picks the findings worth proving from `findings.final.json` (action
|
|
5
|
+
must-fix or should-fix, at most 8, highest score first),
|
|
6
6
|
takes the fenced `magpie-proof` block below, fills its four placeholders, and writes
|
|
7
7
|
one prompt file per finding:
|
|
8
8
|
|
|
@@ -56,7 +56,10 @@ Diff: <<DIFF_PATH>>
|
|
|
56
56
|
real dependency never would proves nothing.
|
|
57
57
|
4. Run only that file, with colour off (`--no-color`, `CI=1`), and in a way that does
|
|
58
58
|
not compile or type-check the whole project: other provers' half-written files sit
|
|
59
|
-
beside yours. Read the output.
|
|
59
|
+
beside yours. Read the output. Anything you save outside the test file, such as the
|
|
60
|
+
run's output, goes in a directory of your own from `mktemp -d`, never a scratchpad or
|
|
61
|
+
temp path another session shares: other provers write there too, and their output
|
|
62
|
+
is not your result.
|
|
60
63
|
5. Copy the test's full source and the last 40 lines of output (at most) into your
|
|
61
64
|
result. Then, whatever the outcome, `not-proven` included, delete the test file and
|
|
62
65
|
anything its run created (snapshots, fixtures). Change no other file in the working
|
|
@@ -202,3 +202,31 @@ test('history with only leads carries the leads heading and no repeats preamble'
|
|
|
202
202
|
].join('\n'),
|
|
203
203
|
)
|
|
204
204
|
})
|
|
205
|
+
|
|
206
|
+
test('already-raised leaves out comments from github-actions, which posts CI output', () => {
|
|
207
|
+
const out = renderAlreadyRaised({
|
|
208
|
+
activity: {
|
|
209
|
+
checks: [],
|
|
210
|
+
threads: [],
|
|
211
|
+
comments: [
|
|
212
|
+
{ author: 'github-actions', body: '<h2>Coverage Report</h2>', magpie: false },
|
|
213
|
+
{ author: 'coderabbitai', body: 'This retry never backs off.', magpie: false },
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
previous: null,
|
|
217
|
+
})
|
|
218
|
+
expect(out).toBe('PR comments:\n- coderabbitai: This retry never backs off.')
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('already-raised is (none) when the only comments are CI output', () => {
|
|
222
|
+
expect(
|
|
223
|
+
renderAlreadyRaised({
|
|
224
|
+
activity: {
|
|
225
|
+
checks: [],
|
|
226
|
+
threads: [],
|
|
227
|
+
comments: [{ author: 'github-actions', body: '<h2>Coverage Report</h2>', magpie: false }],
|
|
228
|
+
},
|
|
229
|
+
previous: null,
|
|
230
|
+
}),
|
|
231
|
+
).toBe('(none)')
|
|
232
|
+
})
|
|
@@ -44,17 +44,24 @@ const REPRO = {
|
|
|
44
44
|
output: 'expected 1, received undefined',
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
test('
|
|
47
|
+
test('findings marked must-fix or should-fix are selected whatever their impact', () => {
|
|
48
48
|
const selected = selectForProof(
|
|
49
49
|
[
|
|
50
50
|
finding('high-should', HIGH_SHOULD),
|
|
51
51
|
finding('medium-should', MEDIUM_SHOULD),
|
|
52
|
+
finding('low-should', { ...HIGH_SHOULD, impact: 'low' }),
|
|
52
53
|
finding('high-consider', HIGH_CONSIDER),
|
|
54
|
+
finding('high-optional', { ...HIGH_SHOULD, action: 'optional' }),
|
|
53
55
|
finding('critical-must', CRITICAL_MUST),
|
|
54
56
|
],
|
|
55
57
|
8,
|
|
56
58
|
)
|
|
57
|
-
expect(selected.map((f) => f.id)).toEqual([
|
|
59
|
+
expect(selected.map((f) => f.id)).toEqual([
|
|
60
|
+
'critical-must',
|
|
61
|
+
'high-should',
|
|
62
|
+
'medium-should',
|
|
63
|
+
'low-should',
|
|
64
|
+
])
|
|
58
65
|
})
|
|
59
66
|
|
|
60
67
|
test('selection keeps the highest-scoring findings when there are more than the cap', () => {
|
|
@@ -114,6 +114,15 @@ test('references/proof.md carries every placeholder proof-prompt fills', async (
|
|
|
114
114
|
}
|
|
115
115
|
})
|
|
116
116
|
|
|
117
|
+
test("references/proof.md keeps each prover's scratch output in a directory of its own", async () => {
|
|
118
|
+
// On PR 254 a prover picked up another prover's run output from the session
|
|
119
|
+
// scratchpad every subagent shares, and nearly reported it as its own.
|
|
120
|
+
const text = await readFile(ref('proof.md'), 'utf8')
|
|
121
|
+
const block = text.match(/^(`{3,4})magpie-proof\n([\s\S]*?)\n\1[ \t]*$/m)?.[2] ?? ''
|
|
122
|
+
expect(block).toContain('mktemp -d')
|
|
123
|
+
expect(block).toMatch(/never a scratchpad or\s+temp path another session shares/)
|
|
124
|
+
})
|
|
125
|
+
|
|
117
126
|
test('references/proof.md asks for the result shape proof-apply accepts', async () => {
|
|
118
127
|
const text = await readFile(ref('proof.md'), 'utf8')
|
|
119
128
|
const block = text.match(/^(`{3,4})magpie-proof\n([\s\S]*?)\n\1[ \t]*$/m)?.[2] ?? ''
|
|
@@ -42,6 +42,12 @@ function joinSections(sections: string[][]): string {
|
|
|
42
42
|
.join('\n\n')
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// The account GitHub Actions posts as: coverage tables, deploy previews and other
|
|
46
|
+
// CI output, which reaches the review as checks. Review bots post as their own
|
|
47
|
+
// apps, and what they raise still counts. gh prints the login without `[bot]`,
|
|
48
|
+
// the REST API with it.
|
|
49
|
+
const CI_AUTHORS = new Set(['github-actions', 'github-actions[bot]'])
|
|
50
|
+
|
|
45
51
|
function raisedSections(input: Pick<History, 'activity' | 'previous'>): string[][] {
|
|
46
52
|
const threads = (input.activity?.threads ?? [])
|
|
47
53
|
.filter((t) => !t.resolved)
|
|
@@ -50,9 +56,9 @@ function raisedSections(input: Pick<History, 'activity' | 'previous'>): string[]
|
|
|
50
56
|
const outdated = t.outdated ? ' [outdated]' : ''
|
|
51
57
|
return `- ${location(t.file, t.line)} (${who})${outdated}: ${flatten(t.body)}`
|
|
52
58
|
})
|
|
53
|
-
const comments = (input.activity?.comments ?? [])
|
|
54
|
-
(c) =>
|
|
55
|
-
|
|
59
|
+
const comments = (input.activity?.comments ?? [])
|
|
60
|
+
.filter((c) => !CI_AUTHORS.has(c.author))
|
|
61
|
+
.map((c) => `- ${c.magpie ? 'magpie, earlier run' : c.author}: ${flatten(c.body)}`)
|
|
56
62
|
const dismissed = (input.previous?.findings ?? []).flatMap((f) =>
|
|
57
63
|
f.label === 'dismissed' ? [`- ${location(f.file, f.line)} [${f.reason}]: ${f.title}`] : [],
|
|
58
64
|
)
|
|
@@ -33,10 +33,10 @@ export type ProofDropped = {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function selectForProof(findings: ReviewFinding[], cap: number): ReviewFinding[] {
|
|
36
|
+
// Action, not impact: the critic keeps a confirmed defect at should-fix even when
|
|
37
|
+
// it rates the impact low, and a real PR left nothing high to prove.
|
|
36
38
|
const eligible = findings.filter(
|
|
37
|
-
(f) =>
|
|
38
|
-
(f.risk.impact === 'critical' || f.risk.impact === 'high') &&
|
|
39
|
-
(f.risk.action === 'must-fix' || f.risk.action === 'should-fix'),
|
|
39
|
+
(f) => f.risk.action === 'must-fix' || f.risk.action === 'should-fix',
|
|
40
40
|
)
|
|
41
41
|
// Scored from risk here, not read from `score`: the peer reviewer may have
|
|
42
42
|
// changed risk or added findings after dedupe set it.
|
package/skills/magpie/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magpie",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Interactive PR review pipeline. Runs five parallel specialist subagents (security, bugs, performance, code-smells, architecture) plus a once-per-PR checks pass that finds tests and controls able to pass without proving their purpose, drops findings whose quoted evidence is not in the code, dedupes, runs critic subagents that re-check each finding against the worktree and set its risk label, peer-reviews via codex exec (falling back to a Claude second opinion when codex is unavailable), and serves an interactive HTML report for selecting or dismissing findings to post via gh, recording the outcome per finding as labels. Bundles a Bun CLI put on PATH by the skill's postinstall step under a bunx install, or by the plugin's bin/ under a Claude Code plugin install. Use when the user asks to review a GitHub pull request. Local mode (setup --local) runs the same pipeline on the current branch's diff from its merge base, uncommitted and untracked work included, against the caller's live tree, with no server or posting, and hands the ranked findings back in the terminal for an implementing or orchestrating agent to address. Splits oversized diffs into budgeted shards and rebuilds the diff from the local clone when gh pr diff refuses it.",
|
|
5
5
|
"author": "iceinvein",
|
|
6
6
|
"type": "prompt",
|