@capybearista/opencode-adversarial-review 1.0.0 → 2.0.1
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/README.md +94 -88
- package/commands/adversarial-review.md +28 -0
- package/commands/constructive-review.md +30 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +423 -169
- package/dist/index.js.map +1 -1
- package/dist/prompt.d.ts +6 -0
- package/dist/prompt.js +221 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +12 -9
- package/server.js +1 -0
- /package/{LICENSE → LICENSE.txt} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,176 +1,430 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, open, readFile, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { Plugin } from "@opencode/plugin";
|
|
6
|
+
import { ADVERSARIAL_REVIEWER_SYSTEM_PROMPT, REVIEWER_SYSTEM_PROMPT } from "./prompt.js";
|
|
1
7
|
const PLUGIN_ID = "capybearista.opencode-adversarial-review";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Do not
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- observability gaps that would hide failure or make recovery harder
|
|
34
|
-
</attack_surface>
|
|
35
|
-
|
|
36
|
-
<review_method>
|
|
37
|
-
Actively try to disprove the change.
|
|
38
|
-
Look for violated invariants, missing guards, unhandled failure paths, and assumptions that stop being true under stress.
|
|
39
|
-
Trace how bad inputs, retries, concurrent actions, or partially completed operations move through the code.
|
|
40
|
-
If the user supplied a focus area, weight it heavily, but still report any other material issue you can defend.
|
|
41
|
-
If the diff context is limited (only stat, no full diff), use the available tools (read, grep, glob) to inspect specific files before finalizing.
|
|
42
|
-
</review_method>
|
|
43
|
-
|
|
44
|
-
<context_type>
|
|
45
|
-
The diff context either contains a full inline diff (for changes to 1-2 files) or a summary stat only (for larger changes). If you see a stat-only section without a full inline diff, use your tools to inspect the changed files directly. If you see a full inline diff, use it as primary evidence and supplement with tools as needed.
|
|
46
|
-
</context_type>
|
|
47
|
-
|
|
48
|
-
<finding_bar>
|
|
49
|
-
Report only material findings.
|
|
50
|
-
Do not include style feedback, naming feedback, low-value cleanup, or speculative concerns without evidence.
|
|
51
|
-
A finding should answer:
|
|
52
|
-
1. What can go wrong?
|
|
53
|
-
2. Why is this code path vulnerable?
|
|
54
|
-
3. What is the likely impact?
|
|
55
|
-
4. What concrete change would reduce the risk?
|
|
56
|
-
</finding_bar>
|
|
57
|
-
|
|
58
|
-
<structured_output_contract>
|
|
59
|
-
Output valid JSON matching this schema:
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
"verdict": "approve" | "needs-attention",
|
|
63
|
-
"summary": "terse ship/no-ship assessment",
|
|
64
|
-
"findings": [
|
|
8
|
+
// Hex is required; plugin-defined agents do not resolve theme color names.
|
|
9
|
+
const REVIEWER_COLOR = "#f59e0b";
|
|
10
|
+
// Both command templates version together. The integer `managed_version`
|
|
11
|
+
// frontmatter stamp is the ownership marker: keeping it means the plugin
|
|
12
|
+
// refreshes the file from the bundled template on `/reload` or restart,
|
|
13
|
+
// removing it takes ownership and the file is preserved with a warning.
|
|
14
|
+
// Unknown or newer stamps are preserved too, so a downgrade never overwrites a
|
|
15
|
+
// newer plugin's file.
|
|
16
|
+
export const CURRENT_TEMPLATE_VERSION = 2;
|
|
17
|
+
// Every version this build knows how to refresh in place, oldest first.
|
|
18
|
+
export const KNOWN_TEMPLATE_VERSIONS = [1, 2];
|
|
19
|
+
// O_NOFOLLOW closes the lstat-to-read and lstat-to-write races on the refresh
|
|
20
|
+
// path: a symlink swapped in after the check makes the next operation fail
|
|
21
|
+
// with ELOOP instead of following or truncating the link target. O_CREAT
|
|
22
|
+
// tolerates the file disappearing between the EEXIST check and the refresh.
|
|
23
|
+
// Platforms without O_NOFOLLOW fall back to the lstat check and setup warns.
|
|
24
|
+
const OVERWRITE_FLAGS = constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | (constants.O_NOFOLLOW ?? 0);
|
|
25
|
+
const READ_FLAGS = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0);
|
|
26
|
+
function doNotInvokeDescription(kind) {
|
|
27
|
+
return `Do not invoke this agent directly. It is the ${kind} code-review agent, invocable only by the user.`;
|
|
28
|
+
}
|
|
29
|
+
// One entry per reviewer. Setup loops both the install and the registration so
|
|
30
|
+
// every reviewer shares one set of mechanics and differs only in identity,
|
|
31
|
+
// command file, and system prompt.
|
|
32
|
+
const REVIEWERS = [
|
|
33
|
+
{
|
|
34
|
+
agentId: "adversarial-reviewer",
|
|
35
|
+
commandFilename: "adversarial-review.md",
|
|
36
|
+
description: doNotInvokeDescription("adversarial"),
|
|
37
|
+
systemPrompt: ADVERSARIAL_REVIEWER_SYSTEM_PROMPT,
|
|
38
|
+
},
|
|
65
39
|
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
40
|
+
agentId: "constructive-reviewer",
|
|
41
|
+
commandFilename: "constructive-review.md",
|
|
42
|
+
description: doNotInvokeDescription("constructive"),
|
|
43
|
+
systemPrompt: REVIEWER_SYSTEM_PROMPT,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
const REVIEWER_AGENT_ID_LIST = REVIEWERS.map((reviewer) => `"${reviewer.agentId}"`).join(" and ");
|
|
47
|
+
// Ordered for the host's last-match-wins evaluation: defaults denied first,
|
|
48
|
+
// read-only allows next, and the sensitive-read denies after the read allow.
|
|
49
|
+
const REVIEWER_PERMISSIONS = [
|
|
50
|
+
{ action: "*", resource: "*", effect: "deny" },
|
|
51
|
+
{ action: "subagent", resource: "*", effect: "deny" },
|
|
52
|
+
{ action: "edit", resource: "*", effect: "deny" },
|
|
53
|
+
{ action: "write", resource: "*", effect: "deny" },
|
|
54
|
+
{ action: "patch", resource: "*", effect: "deny" },
|
|
55
|
+
{ action: "webfetch", resource: "*", effect: "deny" },
|
|
56
|
+
{ action: "websearch", resource: "*", effect: "deny" },
|
|
57
|
+
{ action: "question", resource: "*", effect: "deny" },
|
|
58
|
+
{ action: "skill", resource: "*", effect: "deny" },
|
|
59
|
+
{ action: "external_directory", resource: "*", effect: "deny" },
|
|
60
|
+
{ action: "shell", resource: "*", effect: "deny" },
|
|
61
|
+
{ action: "read", resource: "*", effect: "allow" },
|
|
62
|
+
{ action: "glob", resource: "*", effect: "allow" },
|
|
63
|
+
{ action: "grep", resource: "*", effect: "allow" },
|
|
64
|
+
{ action: "shell", resource: "git blame*", effect: "allow" },
|
|
65
|
+
{ action: "shell", resource: "git branch --show-current*", effect: "allow" },
|
|
66
|
+
{ action: "shell", resource: "git diff*", effect: "allow" },
|
|
67
|
+
{ action: "shell", resource: "git log*", effect: "allow" },
|
|
68
|
+
{ action: "shell", resource: "git ls-files*", effect: "allow" },
|
|
69
|
+
{ action: "shell", resource: "git merge-base*", effect: "allow" },
|
|
70
|
+
{ action: "shell", resource: "git remote -v*", effect: "allow" },
|
|
71
|
+
{ action: "shell", resource: "git rev-list*", effect: "allow" },
|
|
72
|
+
{ action: "shell", resource: "git rev-parse*", effect: "allow" },
|
|
73
|
+
{ action: "shell", resource: "git show*", effect: "allow" },
|
|
74
|
+
{ action: "shell", resource: "git stash list*", effect: "allow" },
|
|
75
|
+
{ action: "shell", resource: "git stash show*", effect: "allow" },
|
|
76
|
+
{ action: "shell", resource: "git status*", effect: "allow" },
|
|
77
|
+
// `gh` is allowlisted to the read-only PR surface only, plus the
|
|
78
|
+
// `gh auth status*` diagnostic. Order is load-bearing: evaluation is
|
|
79
|
+
// last-match-wins, so the `gh *` catch-all deny must come before the specific
|
|
80
|
+
// allows (after them it would override them), and the specific allows stay
|
|
81
|
+
// ordered most-specific-last. The token-printing forms of the diagnostic are
|
|
82
|
+
// denied after its allow: `--show-token` and its `-t` short form would print
|
|
83
|
+
// the stored credential, while the bare diagnostic stays allowed.
|
|
84
|
+
{ action: "shell", resource: "gh *", effect: "deny" },
|
|
85
|
+
{ action: "shell", resource: "gh pr view*", effect: "allow" },
|
|
86
|
+
{ action: "shell", resource: "gh pr diff*", effect: "allow" },
|
|
87
|
+
{ action: "shell", resource: "gh auth status*", effect: "allow" },
|
|
88
|
+
{ action: "shell", resource: "gh auth status*--show-token*", effect: "deny" },
|
|
89
|
+
{ action: "shell", resource: "gh auth status*-t*", effect: "deny" },
|
|
90
|
+
// Denies below must stay after the allows: `--ext-diff` and `--textconv`
|
|
91
|
+
// execute configured diff drivers, and `--output` writes the rendered diff to
|
|
92
|
+
// an arbitrary file.
|
|
93
|
+
{ action: "shell", resource: "git diff*--ext-diff*", effect: "deny" },
|
|
94
|
+
{ action: "shell", resource: "git diff*--textconv*", effect: "deny" },
|
|
95
|
+
{ action: "shell", resource: "git diff*--output*", effect: "deny" },
|
|
96
|
+
{ action: "shell", resource: "git show*--ext-diff*", effect: "deny" },
|
|
97
|
+
{ action: "shell", resource: "git show*--textconv*", effect: "deny" },
|
|
98
|
+
{ action: "shell", resource: "git show*--output*", effect: "deny" },
|
|
99
|
+
{ action: "shell", resource: "git log*--ext-diff*", effect: "deny" },
|
|
100
|
+
{ action: "shell", resource: "git log*--textconv*", effect: "deny" },
|
|
101
|
+
{ action: "shell", resource: "git log*--output*", effect: "deny" },
|
|
102
|
+
{ action: "shell", resource: "git stash show*--ext-diff*", effect: "deny" },
|
|
103
|
+
{ action: "shell", resource: "git stash show*--textconv*", effect: "deny" },
|
|
104
|
+
{ action: "shell", resource: "git stash show*--output*", effect: "deny" },
|
|
105
|
+
// `git diff --no-index` reads arbitrary paths and `git show <rev>:<path>`
|
|
106
|
+
// prints a blob directly, bypassing the read/glob/grep `.env` denies. These
|
|
107
|
+
// denies must stay after the `git diff*` / `git show*` allows. Only the
|
|
108
|
+
// colon-path `.env` / `.env.*` leaf forms are covered; other secret files
|
|
109
|
+
// such as `*.pem` remain readable and are a known limitation.
|
|
110
|
+
{ action: "shell", resource: "git diff*--no-index*", effect: "deny" },
|
|
111
|
+
{ action: "shell", resource: "git show*:*.env", effect: "deny" },
|
|
112
|
+
{ action: "shell", resource: "git show*:*.env.*", effect: "deny" },
|
|
113
|
+
// `.env.example` is not secret material, so it stays readable at a revision
|
|
114
|
+
// like it does through read/glob/grep; this allow must stay after the two
|
|
115
|
+
// denies above (last-match-wins).
|
|
116
|
+
{ action: "shell", resource: "git show*:*.env.example", effect: "allow" },
|
|
117
|
+
// Order re-assertion: the allow above is full-string anchored, so it also
|
|
118
|
+
// matches any command ending in `.env.example` and overrides every earlier
|
|
119
|
+
// rule that command matches. The `git show` engine-flag denies and the
|
|
120
|
+
// secret-then-more-args denies are therefore repeated after it: the engine
|
|
121
|
+
// patterns must outrank the trailing allow for `git show --output=... /
|
|
122
|
+
// --ext-diff ... <rev>:.env.example`, and the `.env` patterns must catch a
|
|
123
|
+
// secret colon-path followed by any further argument (multi-object exfil and
|
|
124
|
+
// trailing flags such as `git show HEAD:.env --stat`). These duplicates are
|
|
125
|
+
// intentional; the earlier copies sit before the allow and lose to it.
|
|
126
|
+
//
|
|
127
|
+
// Pattern shape notes: the inner `*` in `:*.env` mirrors the original
|
|
128
|
+
// `git show*:*.env` deny so directory-prefixed secrets are covered, not just
|
|
129
|
+
// a leaf at the repository root. The `* *` tail on the `.env.*` deny is
|
|
130
|
+
// deliberate: the host folds a trailing `" .*"` pattern into an optional
|
|
131
|
+
// argument group, so a single trailing ` *` would also match a bare
|
|
132
|
+
// `.env.example` read; the doubled pair makes the following argument required.
|
|
133
|
+
{ action: "shell", resource: "git show*--ext-diff*", effect: "deny" },
|
|
134
|
+
{ action: "shell", resource: "git show*--textconv*", effect: "deny" },
|
|
135
|
+
{ action: "shell", resource: "git show*--output*", effect: "deny" },
|
|
136
|
+
{ action: "shell", resource: "git show*:*.env *", effect: "deny" },
|
|
137
|
+
{ action: "shell", resource: "git show*:*.env.* * *", effect: "deny" },
|
|
138
|
+
{ action: "read", resource: "*.env", effect: "deny" },
|
|
139
|
+
{ action: "read", resource: "*.env.*", effect: "deny" },
|
|
140
|
+
{ action: "read", resource: "*.env.example", effect: "allow" },
|
|
141
|
+
{ action: "glob", resource: "*.env", effect: "deny" },
|
|
142
|
+
{ action: "glob", resource: "*.env.*", effect: "deny" },
|
|
143
|
+
{ action: "glob", resource: "*.env.example", effect: "allow" },
|
|
144
|
+
{ action: "grep", resource: "*.env", effect: "deny" },
|
|
145
|
+
{ action: "grep", resource: "*.env.*", effect: "deny" },
|
|
146
|
+
{ action: "grep", resource: "*.env.example", effect: "allow" },
|
|
147
|
+
];
|
|
148
|
+
function hasRule(rules, rule) {
|
|
149
|
+
return rules.some((existing) => existing.action === rule.action &&
|
|
150
|
+
existing.resource === rule.resource &&
|
|
151
|
+
existing.effect === rule.effect);
|
|
152
|
+
}
|
|
153
|
+
// Rules are merged additively: host-defined rules are preserved, exact
|
|
154
|
+
// duplicates of an inherited host rule are skipped, and pre-existing host
|
|
155
|
+
// denies are re-appended after the plugin rules. Evaluation is last-match-wins,
|
|
156
|
+
// so a host deny must outrank any plugin allow for the same resource.
|
|
157
|
+
// Duplicates inside `rules` itself are kept on purpose: a later copy re-asserts
|
|
158
|
+
// a rule that an intermediate allow would otherwise override.
|
|
159
|
+
function applyRules(agent, rules) {
|
|
160
|
+
const inherited = Array.isArray(agent.permissions) ? agent.permissions : [];
|
|
161
|
+
const hostDenies = inherited.filter((rule) => rule.effect === "deny");
|
|
162
|
+
const merged = inherited.filter((rule) => rule.effect !== "deny");
|
|
163
|
+
for (const rule of rules) {
|
|
164
|
+
if (!hasRule(inherited, rule))
|
|
165
|
+
merged.push(rule);
|
|
166
|
+
}
|
|
167
|
+
agent.permissions = [...merged, ...hostDenies];
|
|
168
|
+
}
|
|
169
|
+
function configureReviewerAgent(editor, reviewer) {
|
|
170
|
+
const existing = editor.get(reviewer.agentId);
|
|
171
|
+
editor.update(reviewer.agentId, (agent) => {
|
|
172
|
+
agent.mode = "subagent";
|
|
173
|
+
agent.hidden = true;
|
|
174
|
+
agent.description = reviewer.description;
|
|
175
|
+
agent.system = existing?.system ?? reviewer.systemPrompt;
|
|
176
|
+
agent.color = existing?.color ?? REVIEWER_COLOR;
|
|
177
|
+
// The reviewer runs unattended, so inherited ask rules are dropped instead of
|
|
178
|
+
// stalling on a user prompt; the explicit rules below keep it sandboxed.
|
|
179
|
+
const inherited = Array.isArray(agent.permissions) ? agent.permissions : [];
|
|
180
|
+
agent.permissions = inherited.filter((rule) => rule.effect !== "ask");
|
|
181
|
+
applyRules(agent, REVIEWER_PERMISSIONS);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function errorMessage(error) {
|
|
185
|
+
return error instanceof Error ? error.message : String(error);
|
|
186
|
+
}
|
|
187
|
+
async function disposeRegistrations(disposers, logWarn) {
|
|
188
|
+
const results = await Promise.allSettled(disposers.map(async (dispose) => dispose()));
|
|
189
|
+
for (const result of results) {
|
|
190
|
+
if (result.status === "rejected") {
|
|
191
|
+
logWarn(`[${PLUGIN_ID}] Failed to dispose an agent registration: ${errorMessage(result.reason)}. The host may retain the registration until plugins reload.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// @opencode/plugin 2.0.2 exposes no logging domain on the plugin context, so
|
|
196
|
+
// console.error / console.warn / console.info are the fallback. Hosts that add
|
|
197
|
+
// an `app.log` sink receive the same messages as structured entries; wording
|
|
198
|
+
// never changes between the two paths. The fallback console method is captured
|
|
199
|
+
// once per createHostLogger call, so replace console methods before setup.
|
|
200
|
+
function createHostLogger(ctx, level) {
|
|
201
|
+
const fallbacks = {
|
|
202
|
+
error: console.error,
|
|
203
|
+
warn: console.warn,
|
|
204
|
+
info: console.info,
|
|
205
|
+
};
|
|
206
|
+
const fallback = fallbacks[level];
|
|
207
|
+
const sink = ctx.app?.log;
|
|
208
|
+
if (typeof sink !== "function") {
|
|
209
|
+
return (message) => fallback(message);
|
|
210
|
+
}
|
|
211
|
+
const hostLog = sink;
|
|
212
|
+
return (message) => {
|
|
213
|
+
try {
|
|
214
|
+
void Promise.resolve(hostLog.call(ctx.app, { service: PLUGIN_ID, level, message })).catch(() => fallback(message));
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
fallback(message);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function commandFilePath(commandFilename) {
|
|
222
|
+
const override = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
223
|
+
const configDirectory = override ? override : join(homedir(), ".config", "opencode");
|
|
224
|
+
return join(configDirectory, "commands", commandFilename);
|
|
225
|
+
}
|
|
226
|
+
export function managedVersionOf(markdown) {
|
|
227
|
+
const value = frontmatterFieldOf(markdown, "managed_version");
|
|
228
|
+
if (value === undefined || !/^[0-9]+$/.test(value))
|
|
229
|
+
return undefined;
|
|
230
|
+
const version = Number(value);
|
|
231
|
+
return version > 0 ? version : undefined;
|
|
232
|
+
}
|
|
233
|
+
function frontmatterFieldOf(markdown, field) {
|
|
234
|
+
const block = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
235
|
+
if (!block?.[1])
|
|
236
|
+
return undefined;
|
|
237
|
+
for (const line of block[1].split("\n")) {
|
|
238
|
+
const separator = line.indexOf(":");
|
|
239
|
+
if (separator <= 0 || line.slice(0, separator).trim() !== field)
|
|
240
|
+
continue;
|
|
241
|
+
return line.slice(separator + 1).trim();
|
|
242
|
+
}
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
export function isManagedUpgrade(installedVersion, knownVersions, currentVersion) {
|
|
246
|
+
return knownVersions.includes(installedVersion) && installedVersion <= currentVersion;
|
|
247
|
+
}
|
|
248
|
+
// On platforms without `constants.O_NOFOLLOW` (for example Windows) the refresh
|
|
249
|
+
// read and write keep the earlier `lstat` check but cannot close the symlink
|
|
250
|
+
// swap race around it. Surface the degradation once instead of failing loud.
|
|
251
|
+
function warnIfNoFollowUnavailable(logWarn, noFollowFlag) {
|
|
252
|
+
if (noFollowFlag === undefined) {
|
|
253
|
+
logWarn(`[${PLUGIN_ID}] O_NOFOLLOW is unavailable on this platform; managed command file refreshes keep the lstat check on the leaf file but cannot close the symlink-swap race around it.`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function warnExistingFile(commandPath, logWarn) {
|
|
257
|
+
logWarn(`[${PLUGIN_ID}] ${commandPath} already exists; leaving it untouched. It may be stale or customized: edit it in place, delete it to reinstall the bundled template, or delete it after removing the plugin to uninstall.`);
|
|
258
|
+
}
|
|
259
|
+
// `wx` makes the first write atomic and refuses to replace anything already at
|
|
260
|
+
// the path; the EEXIST path decides between a managed refresh (a known
|
|
261
|
+
// `managed_version` stamp no newer than the shipped template) and a preserve-
|
|
262
|
+
// and-warn for user-owned, unknown, or newer content. Parent-directory trust:
|
|
263
|
+
// the containing `commands/` directory is assumed trustworthy. A symlinked
|
|
264
|
+
// parent could redirect the write outside the config directory; the
|
|
265
|
+
// no-symlink-following guarantee covers the leaf file only.
|
|
266
|
+
async function installCommandFile(reviewer, logWarn, logInfo) {
|
|
267
|
+
const commandPath = commandFilePath(reviewer.commandFilename);
|
|
268
|
+
const commandName = `/${reviewer.commandFilename.replace(/\.md$/, "")}`;
|
|
269
|
+
const assetUrl = new URL(`../commands/${reviewer.commandFilename}`, import.meta.url);
|
|
270
|
+
let template;
|
|
271
|
+
try {
|
|
272
|
+
template = await readFile(assetUrl, "utf8");
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
throw new Error(`Unable to read the bundled command template at ${assetUrl.pathname}: ${errorMessage(error)}. Neither reviewer agent was registered.`, { cause: error });
|
|
276
|
+
}
|
|
277
|
+
const installFailure = (error) => new Error(`Unable to install the ${commandName} command at ${commandPath}: ${errorMessage(error)}. Create the parent directory and grant write access, then run /reload. Neither reviewer agent was registered.`, { cause: error });
|
|
278
|
+
try {
|
|
279
|
+
await writeFile(commandPath, template, { flag: "wx" });
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
if (error.code !== "EEXIST")
|
|
284
|
+
throw installFailure(error);
|
|
285
|
+
}
|
|
286
|
+
// lstat, not stat: a symlinked leaf is never followed, read, or truncated.
|
|
287
|
+
const stats = await lstat(commandPath).catch((error) => {
|
|
288
|
+
throw installFailure(error);
|
|
289
|
+
});
|
|
290
|
+
if (stats.isSymbolicLink()) {
|
|
291
|
+
warnExistingFile(commandPath, logWarn);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// `open`, not `readFile`: READ_FLAGS carries O_NOFOLLOW so the symlink check
|
|
295
|
+
// is atomic with the read. ELOOP means a symlink was swapped in after lstat.
|
|
296
|
+
let handle;
|
|
297
|
+
let installed;
|
|
298
|
+
let closeFailure;
|
|
299
|
+
try {
|
|
300
|
+
handle = await open(commandPath, READ_FLAGS);
|
|
301
|
+
installed = await handle.readFile("utf8");
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
if (error.code === "ELOOP") {
|
|
305
|
+
warnExistingFile(commandPath, logWarn);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
throw installFailure(error);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
// A close failure must not replace an in-flight read failure; it is
|
|
312
|
+
// captured here and re-raised below only when the read succeeded.
|
|
313
|
+
try {
|
|
314
|
+
await handle?.close();
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
closeFailure = error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// Fail-closed on purpose: a close failure aborts setup rather than continuing silently.
|
|
321
|
+
if (closeFailure !== undefined)
|
|
322
|
+
throw installFailure(closeFailure);
|
|
323
|
+
const installedVersion = managedVersionOf(installed);
|
|
324
|
+
if (installedVersion === undefined ||
|
|
325
|
+
!isManagedUpgrade(installedVersion, KNOWN_TEMPLATE_VERSIONS, CURRENT_TEMPLATE_VERSION)) {
|
|
326
|
+
warnExistingFile(commandPath, logWarn);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
// An explicit open separates a failed open (nothing was truncated, so the
|
|
330
|
+
// intact file must survive) from a failed handle write after O_TRUNC has
|
|
331
|
+
// already run (a truncated or partial file must be unlinked so later setups
|
|
332
|
+
// do not preserve it forever). ELOOP can only come from this open; writes to
|
|
333
|
+
// an already-open handle never re-resolve the path.
|
|
334
|
+
const overwrite = await open(commandPath, OVERWRITE_FLAGS).catch((error) => {
|
|
335
|
+
if (error.code === "ELOOP") {
|
|
336
|
+
warnExistingFile(commandPath, logWarn);
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
throw installFailure(error);
|
|
340
|
+
});
|
|
341
|
+
if (overwrite === undefined)
|
|
342
|
+
return;
|
|
343
|
+
try {
|
|
344
|
+
await overwrite.writeFile(template);
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
// Best-effort unlink returns the path to the fresh `wx` install; on a
|
|
348
|
+
// symlink leaf it removes only the link, never the target.
|
|
349
|
+
await unlink(commandPath).catch(() => { });
|
|
350
|
+
throw installFailure(error);
|
|
351
|
+
}
|
|
352
|
+
finally {
|
|
353
|
+
// Matching fsPromises.writeFile, a close failure after a successful write
|
|
354
|
+
// is not an install failure.
|
|
355
|
+
await overwrite.close().catch(() => { });
|
|
356
|
+
}
|
|
357
|
+
logInfo(`[${PLUGIN_ID}] Updating the managed command file at ${commandPath} from the bundled template (managed_version ${installedVersion}).`);
|
|
358
|
+
}
|
|
359
|
+
// A pre-rename build installed the second reviewer's command as `review.md`
|
|
360
|
+
// with `agent: reviewer`, an id this build no longer registers; the host still
|
|
361
|
+
// discovers that leftover as a broken /review command. Only that exact
|
|
362
|
+
// filename is inspected, and it is deleted only when it is provably ours: the
|
|
363
|
+
// old agent id plus a managed_version stamp this build knows. A missing or
|
|
364
|
+
// unknown stamp could be a user's own file, so it is preserved with a loud
|
|
365
|
+
// warning naming the file, the broken-command risk, and the manual fix.
|
|
366
|
+
const PRE_RENAME_COMMAND_FILENAME = "review.md";
|
|
367
|
+
const PRE_RENAME_REVIEWER_AGENT_ID = "reviewer";
|
|
368
|
+
async function removeStalePreRenameCommand(logWarn, logInfo) {
|
|
369
|
+
const stalePath = commandFilePath(PRE_RENAME_COMMAND_FILENAME);
|
|
370
|
+
let contents;
|
|
371
|
+
try {
|
|
372
|
+
contents = await readFile(stalePath, "utf8");
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
if (error.code === "ENOENT")
|
|
376
|
+
return;
|
|
377
|
+
logWarn(`[${PLUGIN_ID}] Unable to inspect ${stalePath} for a stale pre-rename /review command: ${errorMessage(error)}. If it is not yours, delete it manually so the host stops discovering a broken /review command.`);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (frontmatterFieldOf(contents, "agent") !== PRE_RENAME_REVIEWER_AGENT_ID)
|
|
381
|
+
return;
|
|
382
|
+
const version = managedVersionOf(contents);
|
|
383
|
+
if (version === undefined || !KNOWN_TEMPLATE_VERSIONS.includes(version)) {
|
|
384
|
+
logWarn(`[${PLUGIN_ID}] Found ${stalePath}, a leftover pre-rename /review command for the removed "${PRE_RENAME_REVIEWER_AGENT_ID}" agent without a managed_version stamp this build recognizes; leaving it untouched. That agent no longer exists, so /review is broken: delete that file manually to clear it.`);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
await unlink(stalePath);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
if (error.code !== "ENOENT") {
|
|
392
|
+
logWarn(`[${PLUGIN_ID}] Failed to remove the stale pre-rename command file at ${stalePath}: ${errorMessage(error)}. The "${PRE_RENAME_REVIEWER_AGENT_ID}" agent no longer exists, so /review is broken until you delete that file manually.`);
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
logInfo(`[${PLUGIN_ID}] Removed the stale pre-rename command file at ${stalePath} (managed_version ${version}); it registered /review for the removed "${PRE_RENAME_REVIEWER_AGENT_ID}" agent.`);
|
|
77
397
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
If the change looks safe, say so directly and return no findings.
|
|
95
|
-
</calibration_rules>
|
|
96
|
-
|
|
97
|
-
<final_check>
|
|
98
|
-
Before finalizing, check that each finding is:
|
|
99
|
-
- adversarial rather than stylistic
|
|
100
|
-
- tied to a concrete code location
|
|
101
|
-
- plausible under a real failure scenario
|
|
102
|
-
- actionable for an engineer fixing the issue
|
|
103
|
-
</final_check>`;
|
|
104
|
-
const COMMAND_TEMPLATE = `## Adversarial Review
|
|
105
|
-
|
|
106
|
-
Arguments: $ARGUMENTS
|
|
107
|
-
Target: code changes
|
|
108
|
-
|
|
109
|
-
## Git Context
|
|
110
|
-
|
|
111
|
-
!\`printf "=== Branch ===\\n" && git branch --show-current\`
|
|
112
|
-
!\`printf "=== Status ===\\n" && git status --short --untracked-files=all\`
|
|
113
|
-
!\`printf "=== Recent Commits ===\\n" && git log --oneline -3\`
|
|
114
|
-
!\`printf "=== Changed Files ===\\n" && git diff HEAD --name-only\`
|
|
115
|
-
!\`printf "=== Untracked File Contents ===\\n"; git -c core.quotepath=false ls-files --others --exclude-standard | head -5 | while IFS= read -r f; do printf "--- %s ---\\n" "$f" && cat -- "$f" 2>/dev/null | head -c 16384 && printf "\\n"; done\`
|
|
116
|
-
!\`FILES=\$(git diff HEAD --name-only | wc -l | tr -d ' '); if [ "\$FILES" -gt 0 ] && [ "\$FILES" -le 5 ]; then printf "=== Full Diff ===\\n" && git diff HEAD; else printf "=== Diff Stat ===\\n" && git diff HEAD --stat; fi\``;
|
|
117
|
-
const AGENT_NAME = "adversarial-review";
|
|
118
|
-
const CMD_NAME = "adversarial-review";
|
|
119
|
-
export const AdversarialReviewPlugin = async () => {
|
|
120
|
-
return {
|
|
121
|
-
config: async (cfg) => {
|
|
398
|
+
export default Plugin.define({
|
|
399
|
+
id: PLUGIN_ID,
|
|
400
|
+
async setup(ctx) {
|
|
401
|
+
const disposers = [];
|
|
402
|
+
const logWarn = createHostLogger(ctx, "warn");
|
|
403
|
+
const logInfo = createHostLogger(ctx, "info");
|
|
404
|
+
if (typeof ctx.agent?.transform !== "function") {
|
|
405
|
+
throw new Error(`[${PLUGIN_ID}] agent.transform is unavailable; the ${REVIEWER_AGENT_ID_LIST} agents cannot be registered, so setup was aborted`);
|
|
406
|
+
}
|
|
407
|
+
warnIfNoFollowUnavailable(logWarn, constants.O_NOFOLLOW);
|
|
408
|
+
// Load-bearing split: every command file must install before any agent registers.
|
|
409
|
+
for (const reviewer of REVIEWERS) {
|
|
410
|
+
await installCommandFile(reviewer, logWarn, logInfo);
|
|
411
|
+
}
|
|
412
|
+
await removeStalePreRenameCommand(logWarn, logInfo);
|
|
413
|
+
for (const reviewer of REVIEWERS) {
|
|
122
414
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
"Adversarial code review — challenges implementation approach and design choices";
|
|
128
|
-
agent.mode ??= "subagent";
|
|
129
|
-
agent.model ??= "openai/gpt-5.4";
|
|
130
|
-
agent.temperature ??= 0.1;
|
|
131
|
-
agent.color ??= "warning";
|
|
132
|
-
agent.permission ??= {};
|
|
133
|
-
const agentPerm = agent.permission;
|
|
134
|
-
agentPerm.edit = "deny";
|
|
135
|
-
agentPerm.bash ??= {
|
|
136
|
-
"git blame*": "allow",
|
|
137
|
-
"git branch": "allow",
|
|
138
|
-
"git diff*": "allow",
|
|
139
|
-
"git log*": "allow",
|
|
140
|
-
"git ls-files*": "allow",
|
|
141
|
-
"git merge-base*": "allow",
|
|
142
|
-
"git rev-list*": "allow",
|
|
143
|
-
"git rev-parse*": "allow",
|
|
144
|
-
"git show*": "allow",
|
|
145
|
-
"git stash list*": "allow",
|
|
146
|
-
"git stash show*": "allow",
|
|
147
|
-
"git status*": "allow",
|
|
148
|
-
"*": "deny",
|
|
149
|
-
};
|
|
150
|
-
agentPerm.read ??= "allow";
|
|
151
|
-
agentPerm.glob ??= "allow";
|
|
152
|
-
agentPerm.grep ??= "allow";
|
|
153
|
-
agentPerm.webfetch ??= "deny";
|
|
154
|
-
agentPerm.websearch ??= "deny";
|
|
155
|
-
agent.prompt ??= ADVERSARIAL_REVIEW_PROMPT;
|
|
156
|
-
cfg.command ??= {};
|
|
157
|
-
cfg.command[CMD_NAME] ??= {};
|
|
158
|
-
const cmd = cfg.command[CMD_NAME];
|
|
159
|
-
cmd.description ??= "Run an adversarial code review that challenges the implementation";
|
|
160
|
-
cmd.argumentHint ??= "[--base <ref>] [--scope auto|working-tree|branch] [focus ...]";
|
|
161
|
-
cmd.agent ??= AGENT_NAME;
|
|
162
|
-
cmd.subtask ??= true;
|
|
163
|
-
cmd.template ??= COMMAND_TEMPLATE;
|
|
415
|
+
const registration = await ctx.agent.transform((editor) => {
|
|
416
|
+
configureReviewerAgent(editor, reviewer);
|
|
417
|
+
});
|
|
418
|
+
disposers.push(() => registration.dispose());
|
|
164
419
|
}
|
|
165
|
-
catch (
|
|
166
|
-
|
|
167
|
-
|
|
420
|
+
catch (error) {
|
|
421
|
+
// Registration is all-or-nothing: dispose whatever registered before the
|
|
422
|
+
// failure so a failed setup never leaves a half-registered reviewer pair.
|
|
423
|
+
await disposeRegistrations(disposers, logWarn);
|
|
424
|
+
throw error;
|
|
168
425
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
id: PLUGIN_ID,
|
|
174
|
-
server: AdversarialReviewPlugin,
|
|
175
|
-
};
|
|
426
|
+
}
|
|
427
|
+
return () => disposeRegistrations(disposers, logWarn);
|
|
428
|
+
},
|
|
429
|
+
});
|
|
176
430
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|