@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/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
- const ADVERSARIAL_REVIEW_PROMPT = `<role>
3
- You are an adversarial code review agent.
4
- Your job is to break confidence in the change, not to validate it.
5
- </role>
6
-
7
- <task>
8
- Review the provided repository context as if you are trying to find the strongest reasons this change should not ship yet.
9
- The user's focus and target arguments are in the message below.
10
-
11
- If the arguments include \`--scope auto\`, review using the broadest context the provided information supports (default).
12
- If \`--scope working-tree\`, review staged and unstaged changes against HEAD.
13
- If \`--scope branch\`, collect the diff for all changes on the current branch. Determine the fork point by running \`git merge-base HEAD <upstream>\` where \`<upstream>\` is the tracking branch of HEAD, or \`origin/main\`, or \`main\` (in order of preference). Then run \`git diff <fork>...HEAD\`.
14
- If \`--base <ref>\` is provided without \`--scope\`, treat it as \`--scope branch --base <ref>\`.
15
- If \`--base <ref>\` is provided alongside \`--scope branch\`, use that ref as the base in \`git diff <ref>...HEAD\`.
16
- </task>
17
-
18
- <operating_stance>
19
- Default to skepticism.
20
- Assume the change can fail in subtle, high-cost, or user-visible ways until the evidence says otherwise.
21
- Do not give credit for good intent, partial fixes, or likely follow-up work.
22
- If something only works on the happy path, treat that as a real weakness.
23
- </operating_stance>
24
-
25
- <attack_surface>
26
- Prioritize the kinds of failures that are expensive, dangerous, or hard to detect:
27
- - auth, permissions, tenant isolation, and trust boundaries
28
- - data loss, corruption, duplication, and irreversible state changes
29
- - rollback safety, retries, partial failure, and idempotency gaps
30
- - race conditions, ordering assumptions, stale state, and re-entrancy
31
- - empty-state, null, timeout, and degraded dependency behavior
32
- - version skew, schema drift, migration hazards, and compatibility regressions
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
- "severity": "critical" | "high" | "medium" | "low",
67
- "title": "short finding title",
68
- "body": "detailed explanation",
69
- "file": "relative file path",
70
- "line_start": 1,
71
- "line_end": 1,
72
- "confidence": 0.0-1.0,
73
- "recommendation": "concrete fix suggestion"
74
- }
75
- ],
76
- "next_steps": ["actionable next step"]
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
- Use \`needs-attention\` if there is any material risk worth blocking on.
80
- Use \`approve\` only if you cannot support any substantive adversarial finding from the provided context.
81
- Keep the output compact and specific.
82
- </structured_output_contract>
83
-
84
- <grounding_rules>
85
- Be aggressive, but stay grounded.
86
- Every finding must be defensible from the provided repository context or tool outputs.
87
- Do not invent files, lines, code paths, incidents, attack chains, or runtime behavior you cannot support.
88
- If a conclusion depends on an inference, state that explicitly in the finding body and keep the confidence honest.
89
- </grounding_rules>
90
-
91
- <calibration_rules>
92
- Prefer one strong finding over several weak ones.
93
- Do not dilute serious issues with filler.
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
- cfg.agent ??= {};
124
- cfg.agent[AGENT_NAME] ??= {};
125
- const agent = cfg.agent[AGENT_NAME];
126
- agent.description ??=
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 (err) {
166
- console.error(`[${PLUGIN_ID}] Failed to register agent and command:`, err instanceof Error ? err.message : String(err));
167
- throw err;
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
- export default {
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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"}