-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathadversarial-verify.js
More file actions
60 lines (54 loc) · 2.01 KB
/
Copy pathadversarial-verify.js
File metadata and controls
60 lines (54 loc) · 2.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
export const meta = {
name: 'adversarial-verify',
description: 'Surface candidate findings, then keep only those that survive independent refutation.',
whenToUse:
'Review/audit tasks where false positives are costly. Pass {target, voters?} as args.',
phases: [{ title: 'Find' }, { title: 'Verify' }],
}
const FINDINGS = {
type: 'object',
properties: {
findings: {
type: 'array',
items: {
type: 'object',
properties: { title: { type: 'string' }, detail: { type: 'string' } },
required: ['title', 'detail'],
},
},
},
required: ['findings'],
}
const VERDICT = {
type: 'object',
properties: { refuted: { type: 'boolean' }, reason: { type: 'string' } },
required: ['refuted'],
}
const target = (args && args.target) || 'Review this code for correctness bugs.'
const voters = (args && Number(args.voters)) || 3
// Phase 1 — one agent surfaces candidate findings (typed via a schema).
phase('Find')
log('Finding candidate issues')
const found = await agent(target, { label: 'finder', phase: 'Find', schema: FINDINGS })
const findings = found.findings || []
log(`${findings.length} candidates; verifying each with ${voters} skeptics`)
// Phase 2 — pipeline: each finding streams into a panel of independent skeptics.
// A finding is kept only if a majority fail to refute it.
phase('Verify')
const judged = await pipeline(findings, (finding) =>
parallel(
Array.from({ length: voters }, () => () =>
agent(
`Try to REFUTE this finding using independent reasoning. Default to refuted=true if unsure.\n` +
`Title: ${finding.title}\nDetail: ${finding.detail}`,
{ phase: 'Verify', schema: VERDICT }
)
)
).then((votes) => {
const valid = votes.filter(Boolean)
const refutations = valid.filter((v) => v.refuted).length
return { finding, kept: refutations <= Math.floor(voters / 2) }
})
)
const confirmed = judged.filter(Boolean).filter((j) => j.kept).map((j) => j.finding)
return { confirmed, considered: findings.length }